From 73fb59697382e3abb37f55c9c1a274efb00b0e45 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 26 Aug 2014 16:03:44 +0200 Subject: [PATCH] add libosmium --- ThirdParty/osmium/area/assembler.hpp | 767 ++++++++++++++ .../osmium/area/detail/node_ref_segment.hpp | 257 +++++ ThirdParty/osmium/area/detail/proto_ring.hpp | 274 +++++ .../osmium/area/detail/segment_list.hpp | 216 ++++ .../osmium/area/multipolygon_collector.hpp | 211 ++++ ThirdParty/osmium/area/problem_reporter.hpp | 149 +++ .../area/problem_reporter_exception.hpp | 96 ++ .../osmium/area/problem_reporter_ogr.hpp | 202 ++++ .../osmium/area/problem_reporter_stream.hpp | 96 ++ ThirdParty/osmium/builder/builder.hpp | 179 ++++ ThirdParty/osmium/builder/builder_helper.hpp | 103 ++ .../osmium/builder/osm_object_builder.hpp | 207 ++++ ThirdParty/osmium/config/constexpr.hpp | 43 + ThirdParty/osmium/diff_handler.hpp | 67 ++ ThirdParty/osmium/diff_iterator.hpp | 129 +++ ThirdParty/osmium/diff_visitor.hpp | 104 ++ ThirdParty/osmium/dynamic_handler.hpp | 195 ++++ ThirdParty/osmium/geom/coordinates.hpp | 106 ++ ThirdParty/osmium/geom/factory.hpp | 282 ++++++ ThirdParty/osmium/geom/geojson.hpp | 149 +++ ThirdParty/osmium/geom/geos.hpp | 224 +++++ ThirdParty/osmium/geom/haversine.hpp | 96 ++ .../osmium/geom/mercator_projection.hpp | 109 ++ ThirdParty/osmium/geom/ogr.hpp | 157 +++ ThirdParty/osmium/geom/projection.hpp | 159 +++ ThirdParty/osmium/geom/relations.hpp | 57 ++ ThirdParty/osmium/geom/util.hpp | 71 ++ ThirdParty/osmium/geom/wkb.hpp | 264 +++++ ThirdParty/osmium/geom/wkt.hpp | 142 +++ ThirdParty/osmium/handler.hpp | 101 ++ ThirdParty/osmium/handler/chain.hpp | 128 +++ ThirdParty/osmium/handler/disk_store.hpp | 111 ++ ThirdParty/osmium/handler/dump.hpp | 294 ++++++ .../handler/node_locations_for_ways.hpp | 148 +++ .../osmium/handler/object_relations.hpp | 106 ++ .../osmium/index/detail/mmap_vector_anon.hpp | 78 ++ .../osmium/index/detail/mmap_vector_base.hpp | 183 ++++ .../osmium/index/detail/mmap_vector_file.hpp | 83 ++ ThirdParty/osmium/index/detail/tmpfile.hpp | 62 ++ ThirdParty/osmium/index/detail/typed_mmap.hpp | 227 +++++ ThirdParty/osmium/index/index.hpp | 100 ++ ThirdParty/osmium/index/map.hpp | 156 +++ ThirdParty/osmium/index/map/dummy.hpp | 87 ++ .../osmium/index/map/mmap_vector_anon.hpp | 61 ++ .../osmium/index/map/mmap_vector_file.hpp | 57 ++ ThirdParty/osmium/index/map/sparse_table.hpp | 140 +++ ThirdParty/osmium/index/map/stl_map.hpp | 112 +++ ThirdParty/osmium/index/map/stl_vector.hpp | 61 ++ ThirdParty/osmium/index/map/vector.hpp | 208 ++++ ThirdParty/osmium/index/multimap.hpp | 125 +++ ThirdParty/osmium/index/multimap/hybrid.hpp | 199 ++++ .../index/multimap/mmap_vector_anon.hpp | 58 ++ .../index/multimap/mmap_vector_file.hpp | 54 + .../osmium/index/multimap/stl_multimap.hpp | 151 +++ .../osmium/index/multimap/stl_vector.hpp | 58 ++ ThirdParty/osmium/index/multimap/vector.hpp | 141 +++ ThirdParty/osmium/io/any_compression.hpp | 39 + ThirdParty/osmium/io/any_input.hpp | 41 + ThirdParty/osmium/io/any_output.hpp | 42 + ThirdParty/osmium/io/bzip2_compression.hpp | 196 ++++ ThirdParty/osmium/io/compression.hpp | 240 +++++ ThirdParty/osmium/io/detail/input_format.hpp | 160 +++ .../osmium/io/detail/opl_output_format.hpp | 303 ++++++ ThirdParty/osmium/io/detail/output_format.hpp | 156 +++ ThirdParty/osmium/io/detail/pbf.hpp | 79 ++ .../osmium/io/detail/pbf_input_format.hpp | 681 +++++++++++++ .../osmium/io/detail/pbf_output_format.hpp | 950 ++++++++++++++++++ .../osmium/io/detail/pbf_stringtable.hpp | 196 ++++ ThirdParty/osmium/io/detail/read_thread.hpp | 105 ++ ThirdParty/osmium/io/detail/read_write.hpp | 170 ++++ ThirdParty/osmium/io/detail/write_thread.hpp | 86 ++ .../osmium/io/detail/xml_input_format.hpp | 677 +++++++++++++ .../osmium/io/detail/xml_output_format.hpp | 482 +++++++++ ThirdParty/osmium/io/detail/zlib.hpp | 98 ++ ThirdParty/osmium/io/file.hpp | 319 ++++++ ThirdParty/osmium/io/file_compression.hpp | 68 ++ ThirdParty/osmium/io/file_format.hpp | 74 ++ ThirdParty/osmium/io/gzip_compression.hpp | 132 +++ ThirdParty/osmium/io/header.hpp | 122 +++ ThirdParty/osmium/io/input_iterator.hpp | 139 +++ ThirdParty/osmium/io/opl_output.hpp | 39 + ThirdParty/osmium/io/output_iterator.hpp | 114 +++ ThirdParty/osmium/io/overwrite.hpp | 52 + ThirdParty/osmium/io/pbf_input.hpp | 39 + ThirdParty/osmium/io/pbf_output.hpp | 39 + ThirdParty/osmium/io/reader.hpp | 281 ++++++ ThirdParty/osmium/io/reader_iterator.hpp | 51 + ThirdParty/osmium/io/writer.hpp | 142 +++ ThirdParty/osmium/io/xml_input.hpp | 39 + ThirdParty/osmium/io/xml_output.hpp | 39 + ThirdParty/osmium/memory/buffer.hpp | 523 ++++++++++ ThirdParty/osmium/memory/collection.hpp | 153 +++ ThirdParty/osmium/memory/item.hpp | 178 ++++ ThirdParty/osmium/memory/item_iterator.hpp | 181 ++++ .../osmium/object_pointer_collection.hpp | 112 +++ ThirdParty/osmium/osm.hpp | 48 + ThirdParty/osmium/osm/area.hpp | 172 ++++ ThirdParty/osmium/osm/box.hpp | 207 ++++ ThirdParty/osmium/osm/changeset.hpp | 340 +++++++ ThirdParty/osmium/osm/diff_object.hpp | 156 +++ ThirdParty/osmium/osm/entity.hpp | 55 + ThirdParty/osmium/osm/entity_bits.hpp | 93 ++ ThirdParty/osmium/osm/item_type.hpp | 163 +++ ThirdParty/osmium/osm/location.hpp | 311 ++++++ ThirdParty/osmium/osm/node.hpp | 80 ++ ThirdParty/osmium/osm/node_ref.hpp | 152 +++ ThirdParty/osmium/osm/node_ref_list.hpp | 135 +++ ThirdParty/osmium/osm/object.hpp | 429 ++++++++ ThirdParty/osmium/osm/object_comparisons.hpp | 110 ++ ThirdParty/osmium/osm/relation.hpp | 189 ++++ ThirdParty/osmium/osm/segment.hpp | 105 ++ ThirdParty/osmium/osm/tag.hpp | 140 +++ ThirdParty/osmium/osm/timestamp.hpp | 159 +++ ThirdParty/osmium/osm/types.hpp | 83 ++ ThirdParty/osmium/osm/undirected_segment.hpp | 100 ++ ThirdParty/osmium/osm/way.hpp | 115 +++ ThirdParty/osmium/relations/collector.hpp | 535 ++++++++++ .../osmium/relations/detail/member_meta.hpp | 131 +++ .../osmium/relations/detail/relation_meta.hpp | 136 +++ ThirdParty/osmium/tags/filter.hpp | 148 +++ ThirdParty/osmium/tags/regex_filter.hpp | 58 ++ ThirdParty/osmium/tags/taglist.hpp | 67 ++ ThirdParty/osmium/thread/checked_task.hpp | 106 ++ ThirdParty/osmium/thread/function_wrapper.hpp | 104 ++ ThirdParty/osmium/thread/name.hpp | 61 ++ ThirdParty/osmium/thread/pool.hpp | 180 ++++ ThirdParty/osmium/thread/queue.hpp | 128 +++ ThirdParty/osmium/thread/sorted_queue.hpp | 159 +++ ThirdParty/osmium/util/compatibility.hpp | 47 + ThirdParty/osmium/util/options.hpp | 155 +++ ThirdParty/osmium/util/verbose_output.hpp | 139 +++ ThirdParty/osmium/visitor.hpp | 255 +++++ 132 files changed, 21688 insertions(+) create mode 100644 ThirdParty/osmium/area/assembler.hpp create mode 100644 ThirdParty/osmium/area/detail/node_ref_segment.hpp create mode 100644 ThirdParty/osmium/area/detail/proto_ring.hpp create mode 100644 ThirdParty/osmium/area/detail/segment_list.hpp create mode 100644 ThirdParty/osmium/area/multipolygon_collector.hpp create mode 100644 ThirdParty/osmium/area/problem_reporter.hpp create mode 100644 ThirdParty/osmium/area/problem_reporter_exception.hpp create mode 100644 ThirdParty/osmium/area/problem_reporter_ogr.hpp create mode 100644 ThirdParty/osmium/area/problem_reporter_stream.hpp create mode 100644 ThirdParty/osmium/builder/builder.hpp create mode 100644 ThirdParty/osmium/builder/builder_helper.hpp create mode 100644 ThirdParty/osmium/builder/osm_object_builder.hpp create mode 100644 ThirdParty/osmium/config/constexpr.hpp create mode 100644 ThirdParty/osmium/diff_handler.hpp create mode 100644 ThirdParty/osmium/diff_iterator.hpp create mode 100644 ThirdParty/osmium/diff_visitor.hpp create mode 100644 ThirdParty/osmium/dynamic_handler.hpp create mode 100644 ThirdParty/osmium/geom/coordinates.hpp create mode 100644 ThirdParty/osmium/geom/factory.hpp create mode 100644 ThirdParty/osmium/geom/geojson.hpp create mode 100644 ThirdParty/osmium/geom/geos.hpp create mode 100644 ThirdParty/osmium/geom/haversine.hpp create mode 100644 ThirdParty/osmium/geom/mercator_projection.hpp create mode 100644 ThirdParty/osmium/geom/ogr.hpp create mode 100644 ThirdParty/osmium/geom/projection.hpp create mode 100644 ThirdParty/osmium/geom/relations.hpp create mode 100644 ThirdParty/osmium/geom/util.hpp create mode 100644 ThirdParty/osmium/geom/wkb.hpp create mode 100644 ThirdParty/osmium/geom/wkt.hpp create mode 100644 ThirdParty/osmium/handler.hpp create mode 100644 ThirdParty/osmium/handler/chain.hpp create mode 100644 ThirdParty/osmium/handler/disk_store.hpp create mode 100644 ThirdParty/osmium/handler/dump.hpp create mode 100644 ThirdParty/osmium/handler/node_locations_for_ways.hpp create mode 100644 ThirdParty/osmium/handler/object_relations.hpp create mode 100644 ThirdParty/osmium/index/detail/mmap_vector_anon.hpp create mode 100644 ThirdParty/osmium/index/detail/mmap_vector_base.hpp create mode 100644 ThirdParty/osmium/index/detail/mmap_vector_file.hpp create mode 100644 ThirdParty/osmium/index/detail/tmpfile.hpp create mode 100644 ThirdParty/osmium/index/detail/typed_mmap.hpp create mode 100644 ThirdParty/osmium/index/index.hpp create mode 100644 ThirdParty/osmium/index/map.hpp create mode 100644 ThirdParty/osmium/index/map/dummy.hpp create mode 100644 ThirdParty/osmium/index/map/mmap_vector_anon.hpp create mode 100644 ThirdParty/osmium/index/map/mmap_vector_file.hpp create mode 100644 ThirdParty/osmium/index/map/sparse_table.hpp create mode 100644 ThirdParty/osmium/index/map/stl_map.hpp create mode 100644 ThirdParty/osmium/index/map/stl_vector.hpp create mode 100644 ThirdParty/osmium/index/map/vector.hpp create mode 100644 ThirdParty/osmium/index/multimap.hpp create mode 100644 ThirdParty/osmium/index/multimap/hybrid.hpp create mode 100644 ThirdParty/osmium/index/multimap/mmap_vector_anon.hpp create mode 100644 ThirdParty/osmium/index/multimap/mmap_vector_file.hpp create mode 100644 ThirdParty/osmium/index/multimap/stl_multimap.hpp create mode 100644 ThirdParty/osmium/index/multimap/stl_vector.hpp create mode 100644 ThirdParty/osmium/index/multimap/vector.hpp create mode 100644 ThirdParty/osmium/io/any_compression.hpp create mode 100644 ThirdParty/osmium/io/any_input.hpp create mode 100644 ThirdParty/osmium/io/any_output.hpp create mode 100644 ThirdParty/osmium/io/bzip2_compression.hpp create mode 100644 ThirdParty/osmium/io/compression.hpp create mode 100644 ThirdParty/osmium/io/detail/input_format.hpp create mode 100644 ThirdParty/osmium/io/detail/opl_output_format.hpp create mode 100644 ThirdParty/osmium/io/detail/output_format.hpp create mode 100644 ThirdParty/osmium/io/detail/pbf.hpp create mode 100644 ThirdParty/osmium/io/detail/pbf_input_format.hpp create mode 100644 ThirdParty/osmium/io/detail/pbf_output_format.hpp create mode 100644 ThirdParty/osmium/io/detail/pbf_stringtable.hpp create mode 100644 ThirdParty/osmium/io/detail/read_thread.hpp create mode 100644 ThirdParty/osmium/io/detail/read_write.hpp create mode 100644 ThirdParty/osmium/io/detail/write_thread.hpp create mode 100644 ThirdParty/osmium/io/detail/xml_input_format.hpp create mode 100644 ThirdParty/osmium/io/detail/xml_output_format.hpp create mode 100644 ThirdParty/osmium/io/detail/zlib.hpp create mode 100644 ThirdParty/osmium/io/file.hpp create mode 100644 ThirdParty/osmium/io/file_compression.hpp create mode 100644 ThirdParty/osmium/io/file_format.hpp create mode 100644 ThirdParty/osmium/io/gzip_compression.hpp create mode 100644 ThirdParty/osmium/io/header.hpp create mode 100644 ThirdParty/osmium/io/input_iterator.hpp create mode 100644 ThirdParty/osmium/io/opl_output.hpp create mode 100644 ThirdParty/osmium/io/output_iterator.hpp create mode 100644 ThirdParty/osmium/io/overwrite.hpp create mode 100644 ThirdParty/osmium/io/pbf_input.hpp create mode 100644 ThirdParty/osmium/io/pbf_output.hpp create mode 100644 ThirdParty/osmium/io/reader.hpp create mode 100644 ThirdParty/osmium/io/reader_iterator.hpp create mode 100644 ThirdParty/osmium/io/writer.hpp create mode 100644 ThirdParty/osmium/io/xml_input.hpp create mode 100644 ThirdParty/osmium/io/xml_output.hpp create mode 100644 ThirdParty/osmium/memory/buffer.hpp create mode 100644 ThirdParty/osmium/memory/collection.hpp create mode 100644 ThirdParty/osmium/memory/item.hpp create mode 100644 ThirdParty/osmium/memory/item_iterator.hpp create mode 100644 ThirdParty/osmium/object_pointer_collection.hpp create mode 100644 ThirdParty/osmium/osm.hpp create mode 100644 ThirdParty/osmium/osm/area.hpp create mode 100644 ThirdParty/osmium/osm/box.hpp create mode 100644 ThirdParty/osmium/osm/changeset.hpp create mode 100644 ThirdParty/osmium/osm/diff_object.hpp create mode 100644 ThirdParty/osmium/osm/entity.hpp create mode 100644 ThirdParty/osmium/osm/entity_bits.hpp create mode 100644 ThirdParty/osmium/osm/item_type.hpp create mode 100644 ThirdParty/osmium/osm/location.hpp create mode 100644 ThirdParty/osmium/osm/node.hpp create mode 100644 ThirdParty/osmium/osm/node_ref.hpp create mode 100644 ThirdParty/osmium/osm/node_ref_list.hpp create mode 100644 ThirdParty/osmium/osm/object.hpp create mode 100644 ThirdParty/osmium/osm/object_comparisons.hpp create mode 100644 ThirdParty/osmium/osm/relation.hpp create mode 100644 ThirdParty/osmium/osm/segment.hpp create mode 100644 ThirdParty/osmium/osm/tag.hpp create mode 100644 ThirdParty/osmium/osm/timestamp.hpp create mode 100644 ThirdParty/osmium/osm/types.hpp create mode 100644 ThirdParty/osmium/osm/undirected_segment.hpp create mode 100644 ThirdParty/osmium/osm/way.hpp create mode 100644 ThirdParty/osmium/relations/collector.hpp create mode 100644 ThirdParty/osmium/relations/detail/member_meta.hpp create mode 100644 ThirdParty/osmium/relations/detail/relation_meta.hpp create mode 100644 ThirdParty/osmium/tags/filter.hpp create mode 100644 ThirdParty/osmium/tags/regex_filter.hpp create mode 100644 ThirdParty/osmium/tags/taglist.hpp create mode 100644 ThirdParty/osmium/thread/checked_task.hpp create mode 100644 ThirdParty/osmium/thread/function_wrapper.hpp create mode 100644 ThirdParty/osmium/thread/name.hpp create mode 100644 ThirdParty/osmium/thread/pool.hpp create mode 100644 ThirdParty/osmium/thread/queue.hpp create mode 100644 ThirdParty/osmium/thread/sorted_queue.hpp create mode 100644 ThirdParty/osmium/util/compatibility.hpp create mode 100644 ThirdParty/osmium/util/options.hpp create mode 100644 ThirdParty/osmium/util/verbose_output.hpp create mode 100644 ThirdParty/osmium/visitor.hpp diff --git a/ThirdParty/osmium/area/assembler.hpp b/ThirdParty/osmium/area/assembler.hpp new file mode 100644 index 000000000..5c8e6c906 --- /dev/null +++ b/ThirdParty/osmium/area/assembler.hpp @@ -0,0 +1,767 @@ +#ifndef OSMIUM_AREA_ASSEMBLER_HPP +#define OSMIUM_AREA_ASSEMBLER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace osmium { + + namespace area { + + using osmium::area::detail::ProtoRing; + + struct AssemblerConfig { + + osmium::area::ProblemReporter* problem_reporter; + + // Enables debug output to stderr + bool debug; + + explicit AssemblerConfig(osmium::area::ProblemReporter* pr = nullptr, bool d=false) : + problem_reporter(pr), + debug(d) { + } + + /** + * Enable or disable debug output to stderr. This is for Osmium + * developers only. + */ + void enable_debug_output(bool d=true) { + debug = d; + } + + }; // struct AssemblerConfig + + /** + * Assembles area objects from multipolygon relations and their + * members. This is called by the MultipolygonCollector object + * after all members have been collected. + */ + class Assembler { + + const AssemblerConfig m_config; + + // The way segments + osmium::area::detail::SegmentList m_segment_list; + + // The rings we are building from the way segments + std::list m_rings; + + std::vector m_outer_rings; + std::vector m_inner_rings; + + int m_inner_outer_mismatches { 0 }; + + bool debug() const { + return m_config.debug; + } + + /** + * Checks whether the given NodeRefs have the same location. + * Uses the actual location for the test, not the id. If both + * have the same location, but not the same id, a problem + * point will be added to the list of problem points. + */ + bool has_same_location(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) { + if (nr1.location() != nr2.location()) { + return false; + } + if (nr1.ref() != nr2.ref()) { + if (m_config.problem_reporter) { + m_config.problem_reporter->report_duplicate_node(nr1.ref(), nr2.ref(), nr1.location()); + } + } + return true; + } + + void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Way& way) const { + osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder); + for (const osmium::Tag& tag : way.tags()) { + tl_builder.add_tag(tag.key(), tag.value()); + } + } + + void add_common_tags(osmium::builder::TagListBuilder& tl_builder, std::set& ways) const { + std::map counter; + for (const osmium::Way* way : ways) { + for (const auto& tag : way->tags()) { + std::string kv {tag.key()}; + kv.append(1, '\0'); + kv.append(tag.value()); + ++counter[kv]; + } + } + + size_t num_ways = ways.size(); + for (const auto& t_c : counter) { + if (debug()) { + std::cerr << " tag " << t_c.first << " is used " << t_c.second << " times in " << num_ways << " ways\n"; + } + if (t_c.second == num_ways) { + size_t len = std::strlen(t_c.first.c_str()); + tl_builder.add_tag(t_c.first.c_str(), t_c.first.c_str() + len + 1); + } + } + } + + void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Relation& relation) const { + osmium::tags::KeyFilter filter(true); + filter.add(false, "type").add(false, "created_by").add(false, "source").add(false, "note"); + filter.add(false, "test:id").add(false, "test:section"); + + osmium::tags::KeyFilter::iterator fi_begin(filter, relation.tags().begin(), relation.tags().end()); + osmium::tags::KeyFilter::iterator fi_end(filter, relation.tags().end(), relation.tags().end()); + + auto count = std::distance(fi_begin, fi_end); + + if (debug()) { + std::cerr << " found " << count << " tags on relation (without ignored ones)\n"; + } + + if (count > 0) { + if (debug()) { + std::cerr << " use tags from relation\n"; + } + + // write out all tags except type=* + osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder); + for (const osmium::Tag& tag : relation.tags()) { + if (strcmp(tag.key(), "type")) { + tl_builder.add_tag(tag.key(), tag.value()); + } + } + } else { + if (debug()) { + std::cerr << " use tags from outer ways\n"; + } + std::set ways; + for (const auto& ring : m_outer_rings) { + ring->get_ways(ways); + } + if (ways.size() == 1) { + if (debug()) { + std::cerr << " only one outer way\n"; + } + osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder); + for (const osmium::Tag& tag : (*ways.begin())->tags()) { + tl_builder.add_tag(tag.key(), tag.value()); + } + } else { + if (debug()) { + std::cerr << " multiple outer ways, get common tags\n"; + } + osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder); + add_common_tags(tl_builder, ways); + } + } + } + + /** + * Go through all the rings and find rings that are not closed. + * Problems are reported through the problem reporter. + * + * @returns true if any rings were not closed, false otherwise + */ + bool check_for_open_rings() { + bool open_rings = false; + + for (const auto& ring : m_rings) { + if (!ring.closed()) { + open_rings = true; + if (m_config.problem_reporter) { + m_config.problem_reporter->report_ring_not_closed(ring.get_segment_front().first().location(), ring.get_segment_back().second().location()); + } + } + } + + return open_rings; + } + + /** + * Check whether there are any rings that can be combined with the + * given ring to one larger ring by appending the other ring to + * the end of this ring. + * If the rings can be combined they are and the function returns + * true. + */ + bool possibly_combine_rings_back(ProtoRing& ring) { + const osmium::NodeRef& nr = ring.get_segment_back().second(); + + if (debug()) { + std::cerr << " possibly_combine_rings_back()\n"; + } + for (auto it = m_rings.begin(); it != m_rings.end(); ++it) { + if (&*it != &ring && !it->closed()) { + if (has_same_location(nr, it->get_segment_front().first())) { + if (debug()) { + std::cerr << " ring.last=it->first\n"; + } + ring.merge_ring(*it, debug()); + m_rings.erase(it); + return true; + } + if (has_same_location(nr, it->get_segment_back().second())) { + if (debug()) { + std::cerr << " ring.last=it->last\n"; + } + ring.merge_ring_reverse(*it, debug()); + m_rings.erase(it); + return true; + } + } + } + return false; + } + + /** + * Check whether there are any rings that can be combined with the + * given ring to one larger ring by prepending the other ring to + * the start of this ring. + * If the rings can be combined they are and the function returns + * true. + */ + bool possibly_combine_rings_front(ProtoRing& ring) { + const osmium::NodeRef& nr = ring.get_segment_front().first(); + + if (debug()) { + std::cerr << " possibly_combine_rings_front()\n"; + } + for (auto it = m_rings.begin(); it != m_rings.end(); ++it) { + if (&*it != &ring && !it->closed()) { + if (has_same_location(nr, it->get_segment_back().second())) { + if (debug()) { + std::cerr << " ring.first=it->last\n"; + } + ring.swap_segments(*it); + ring.merge_ring(*it, debug()); + m_rings.erase(it); + return true; + } + if (has_same_location(nr, it->get_segment_front().first())) { + if (debug()) { + std::cerr << " ring.first=it->first\n"; + } + ring.reverse(); + ring.merge_ring(*it, debug()); + m_rings.erase(it); + return true; + } + } + } + return false; + } + + void split_off_subring(osmium::area::detail::ProtoRing& ring, osmium::area::detail::ProtoRing::segments_type::iterator it, osmium::area::detail::ProtoRing::segments_type::iterator it_begin, osmium::area::detail::ProtoRing::segments_type::iterator it_end) { + if (debug()) { + std::cerr << " subring found at: " << *it << "\n"; + } + ProtoRing new_ring(it_begin, it_end); + ring.remove_segments(it_begin, it_end); + if (debug()) { + std::cerr << " split into two rings:\n"; + std::cerr << " " << new_ring << "\n"; + std::cerr << " " << ring << "\n"; + } + m_rings.push_back(std::move(new_ring)); + } + + bool has_closed_subring_back(ProtoRing& ring, const NodeRef& nr) { + if (ring.segments().size() < 3) { + return false; + } + if (debug()) { + std::cerr << " has_closed_subring_back()\n"; + } + auto end = ring.segments().end(); + for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) { + if (has_same_location(nr, it->first())) { + split_off_subring(ring, it, it, end); + return true; + } + } + return false; + } + + bool has_closed_subring_front(ProtoRing& ring, const NodeRef& nr) { + if (ring.segments().size() < 3) { + return false; + } + if (debug()) { + std::cerr << " has_closed_subring_front()\n"; + } + auto end = ring.segments().end(); + for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) { + if (has_same_location(nr, it->second())) { + split_off_subring(ring, it, ring.segments().begin(), it+1); + return true; + } + } + return false; + } + + bool check_for_closed_subring(ProtoRing& ring) { + if (debug()) { + std::cerr << " check_for_closed_subring()\n"; + } + + osmium::area::detail::ProtoRing::segments_type segments(ring.segments().size()); + std::copy(ring.segments().begin(), ring.segments().end(), segments.begin()); + std::sort(segments.begin(), segments.end()); + auto it = std::adjacent_find(segments.begin(), segments.end(), [this](const osmium::area::detail::NodeRefSegment& s1, const osmium::area::detail::NodeRefSegment& s2) { + return has_same_location(s1.first(), s2.first()); + }); + if (it == segments.end()) { + return false; + } + auto r1 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it, it+1); + assert(r1 != ring.segments().end()); + auto r2 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it+1, it+2); + assert(r2 != ring.segments().end()); + + if (debug()) { + std::cerr << " found subring in ring " << ring << " at " << it->first() << "\n"; + } + + auto m = std::minmax(r1, r2); + + ProtoRing new_ring(m.first, m.second); + ring.remove_segments(m.first, m.second); + + if (debug()) { + std::cerr << " split ring1=" << new_ring << "\n"; + std::cerr << " split ring2=" << ring << "\n"; + } + + m_rings.emplace_back(new_ring); + + return true; + } + + void combine_rings_front(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) { + if (debug()) { + std::cerr << " => match at front of ring\n"; + } + ring.add_segment_front(segment); + has_closed_subring_front(ring, segment.first()); + if (possibly_combine_rings_front(ring)) { + check_for_closed_subring(ring); + } + } + + void combine_rings_back(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) { + if (debug()) { + std::cerr << " => match at back of ring\n"; + } + ring.add_segment_back(segment); + has_closed_subring_back(ring, segment.second()); + if (possibly_combine_rings_back(ring)) { + check_for_closed_subring(ring); + } + } + + /** + * Append each outer ring together with its inner rings to the + * area in the buffer. + */ + void add_rings_to_area(osmium::builder::AreaBuilder& builder) const { + for (const ProtoRing* ring : m_outer_rings) { + if (debug()) { + std::cerr << " ring " << *ring << " is outer\n"; + } + { + osmium::builder::OuterRingBuilder ring_builder(builder.buffer(), &builder); + ring_builder.add_node_ref(ring->get_segment_front().first()); + for (const auto& segment : ring->segments()) { + ring_builder.add_node_ref(segment.second()); + } + } + for (ProtoRing* inner : ring->inner_rings()) { + osmium::builder::InnerRingBuilder ring_builder(builder.buffer(), &builder); + ring_builder.add_node_ref(inner->get_segment_front().first()); + for (const auto& segment : inner->segments()) { + ring_builder.add_node_ref(segment.second()); + } + } + } + } + + bool add_to_existing_ring(osmium::area::detail::NodeRefSegment segment) { + int n=0; + for (auto& ring : m_rings) { + if (debug()) { + std::cerr << " check against ring " << n << " " << ring; + } + if (ring.closed()) { + if (debug()) { + std::cerr << " => ring CLOSED\n"; + } + } else { + if (has_same_location(ring.get_segment_back().second(), segment.first())) { + combine_rings_back(segment, ring); + return true; + } + if (has_same_location(ring.get_segment_back().second(), segment.second())) { + segment.swap_locations(); + combine_rings_back(segment, ring); + return true; + } + if (has_same_location(ring.get_segment_front().first(), segment.first())) { + segment.swap_locations(); + combine_rings_front(segment, ring); + return true; + } + if (has_same_location(ring.get_segment_front().first(), segment.second())) { + combine_rings_front(segment, ring); + return true; + } + if (debug()) { + std::cerr << " => no match\n"; + } + } + + ++n; + } + return false; + } + + void check_inner_outer(ProtoRing& ring) { + const osmium::NodeRef& min_node = ring.min_node(); + if (debug()) { + std::cerr << " check_inner_outer min_node=" << min_node << "\n"; + } + + int count = 0; + int above = 0; + + for (auto it = m_segment_list.begin(); it != m_segment_list.end() && it->first().location().x() <= min_node.location().x(); ++it) { + if (!ring.contains(*it)) { + if (debug()) { + std::cerr << " segments for count: " << *it; + } + if (it->to_left_of(min_node.location())) { + ++count; + if (debug()) { + std::cerr << " counted\n"; + } + } else { + if (debug()) { + std::cerr << " not counted\n"; + } + } + if (it->first().location() == min_node.location()) { + if (it->second().location().y() > min_node.location().y()) { + ++above; + } + } + if (it->second().location() == min_node.location()) { + if (it->first().location().y() > min_node.location().y()) { + ++above; + } + } + } + } + + if (debug()) { + std::cerr << " count=" << count << " above=" << above << "\n"; + } + + count += above % 2; + + if (count % 2) { + ring.set_inner(); + } + } + + void check_inner_outer_roles() { + if (debug()) { + std::cerr << " check_inner_outer_roles\n"; + } + + for (const auto ringptr : m_outer_rings) { + for (const auto segment : ringptr->segments()) { + if (!segment.role_outer()) { + ++m_inner_outer_mismatches; + if (debug()) { + std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'outer'\n"; + } + if (m_config.problem_reporter) { + m_config.problem_reporter->report_role_should_be_outer(segment.way()->id(), segment.first().location(), segment.second().location()); + } + } + } + } + for (const auto ringptr : m_inner_rings) { + for (const auto segment : ringptr->segments()) { + if (!segment.role_inner()) { + ++m_inner_outer_mismatches; + if (debug()) { + std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'inner'\n"; + } + if (m_config.problem_reporter) { + m_config.problem_reporter->report_role_should_be_inner(segment.way()->id(), segment.first().location(), segment.second().location()); + } + } + } + } + } + + /** + * Create rings from segments. + */ + bool create_rings() { + m_segment_list.sort(); + m_segment_list.erase_duplicate_segments(); + + // Now we look for segments crossing each other. If there are + // any, the multipolygon is invalid. + // In the future this could be improved by trying to fix those + // cases. + if (m_segment_list.find_intersections(m_config.problem_reporter)) { + return false; + } + + // Now iterator over all segments and add them to rings. Each segment + // is tacked on to either end of an existing ring if possible, or a + // new ring is started with it. + for (const auto& segment : m_segment_list) { + if (debug()) { + std::cerr << " checking segment " << segment << "\n"; + } + if (!add_to_existing_ring(segment)) { + if (debug()) { + std::cerr << " new ring for segment " << segment << "\n"; + } + m_rings.emplace_back(segment); + } + } + + if (debug()) { + std::cerr << " Rings:\n"; + for (const auto& ring : m_rings) { + std::cerr << " " << ring; + if (ring.closed()) { + std::cerr << " (closed)"; + } + std::cerr << "\n"; + } + } + + if (check_for_open_rings()) { + if (debug()) { + std::cerr << " not all rings are closed\n"; + } + return false; + } + + if (debug()) { + std::cerr << " Find inner/outer...\n"; + } + + if (m_rings.size() == 1) { + m_outer_rings.push_back(&m_rings.front()); + } else { + for (auto& ring : m_rings) { + check_inner_outer(ring); + if (ring.outer()) { + if (!ring.is_cw()) { + ring.reverse(); + } + m_outer_rings.push_back(&ring); + } else { + if (ring.is_cw()) { + ring.reverse(); + } + m_inner_rings.push_back(&ring); + } + } + + if (m_outer_rings.size() == 1) { + for (auto inner : m_inner_rings) { + m_outer_rings.front()->add_inner_ring(inner); + } + } else { + // sort outer rings by size, smallest first + std::sort(m_outer_rings.begin(), m_outer_rings.end(), [](ProtoRing* a, ProtoRing* b) { + return a->area() < b->area(); + }); + for (auto inner : m_inner_rings) { + for (auto outer : m_outer_rings) { + if (inner->is_in(outer)) { + outer->add_inner_ring(inner); + break; + } + } + } + } + } + + check_inner_outer_roles(); + + return true; + } + + public: + + typedef osmium::area::AssemblerConfig config_type; + + explicit Assembler(const config_type& config) : + m_config(config), + m_segment_list(config.debug) { + } + + ~Assembler() = default; + + /** + * Assemble an area from the given way. + * The resulting area is put into the out_buffer. + */ + void operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) { + if (m_config.problem_reporter) { + m_config.problem_reporter->set_object(osmium::item_type::way, way.id()); + } + + if (!way.ends_have_same_id()) { + if (m_config.problem_reporter) { + m_config.problem_reporter->report_duplicate_node(way.nodes().front().ref(), way.nodes().back().ref(), way.nodes().front().location()); + } + } + + m_segment_list.extract_segments_from_way(way, "outer"); + + if (debug()) { + std::cerr << "\nBuild way id()=" << way.id() << " segments.size()=" << m_segment_list.size() << "\n"; + } + + // Now create the Area object and add the attributes and tags + // from the relation. + { + osmium::builder::AreaBuilder builder(out_buffer); + builder.initialize_from_object(way); + + if (create_rings()) { + add_tags_to_area(builder, way); + add_rings_to_area(builder); + } + } + out_buffer.commit(); + } + + /** + * Assemble an area from the given relation and its members. + * All members are to be found in the in_buffer at the offsets + * given by the members parameter. + * The resulting area is put into the out_buffer. + */ + void operator()(const osmium::Relation& relation, const std::vector& members, const osmium::memory::Buffer& in_buffer, osmium::memory::Buffer& out_buffer) { + if (m_config.problem_reporter) { + m_config.problem_reporter->set_object(osmium::item_type::relation, relation.id()); + } + + m_segment_list.extract_segments_from_ways(relation, members, in_buffer); + + if (debug()) { + std::cerr << "\nBuild relation id()=" << relation.id() << " members.size()=" << members.size() << " segments.size()=" << m_segment_list.size() << "\n"; + } + + size_t area_offset = out_buffer.committed(); + + // Now create the Area object and add the attributes and tags + // from the relation. + { + osmium::builder::AreaBuilder builder(out_buffer); + builder.initialize_from_object(relation); + + if (create_rings()) { + add_tags_to_area(builder, relation); + add_rings_to_area(builder); + } + } + out_buffer.commit(); + + const osmium::TagList& area_tags = out_buffer.get(area_offset).tags(); // tags of the area we just built + + if (m_inner_outer_mismatches == 0) { + auto memit = relation.members().begin(); + for (size_t offset : members) { + if (!std::strcmp(memit->role(), "inner")) { + const osmium::Way& way = in_buffer.get(offset); + if (way.is_closed() && way.tags().size() > 0) { + osmium::tags::KeyFilter filter(true); + filter.add(false, "created_by").add(false, "source").add(false, "note"); + filter.add(false, "test:id").add(false, "test:section"); + + osmium::tags::KeyFilter::iterator fi_begin(filter, way.tags().begin(), way.tags().end()); + osmium::tags::KeyFilter::iterator fi_end(filter, way.tags().end(), way.tags().end()); + + auto d = std::distance(fi_begin, fi_end); + if (d > 0) { + osmium::tags::KeyFilter::iterator area_fi_begin(filter, area_tags.begin(), area_tags.end()); + osmium::tags::KeyFilter::iterator area_fi_end(filter, area_tags.end(), area_tags.end()); + + if (!std::equal(fi_begin, fi_end, area_fi_begin) || d != std::distance(area_fi_begin, area_fi_end)) { + Assembler assembler(m_config); + assembler(way, out_buffer); + } + } + } + } + ++memit; + } + } + } + + }; // class Assembler + + } // namespace area + +} // namespace osmium + +#endif // OSMIUM_AREA_ASSEMBLER_HPP diff --git a/ThirdParty/osmium/area/detail/node_ref_segment.hpp b/ThirdParty/osmium/area/detail/node_ref_segment.hpp new file mode 100644 index 000000000..62905d675 --- /dev/null +++ b/ThirdParty/osmium/area/detail/node_ref_segment.hpp @@ -0,0 +1,257 @@ +#ifndef OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP +#define OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + class Way; + + namespace area { + + /** + * @brief Namespace for Osmium internal use + */ + namespace detail { + + /** + * This helper class for the Assembler class models a segment. + * Segments are the connection between + * two nodes and they all have their smaller coordinate at the + * beginning of the segment. Smaller, in this case, means smaller x + * coordinate, and if they are the same smaller y coordinate. + */ + class NodeRefSegment { + + osmium::NodeRef m_first; + osmium::NodeRef m_second; + + /// Role of the member this segment was from. + const char* m_role; + + /// Way this segment was from. + const osmium::Way* m_way; + + public: + + void swap_locations() { + using std::swap; + swap(m_first, m_second); + } + + explicit NodeRefSegment() : + m_first(), + m_second(), + m_role(nullptr), + m_way(nullptr) { + } + + explicit NodeRefSegment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2, const char* role, const osmium::Way* way) : + m_first(nr1), + m_second(nr2), + m_role(role), + m_way(way) { + if (nr2.location() < nr1.location()) { + swap_locations(); + } + } + + NodeRefSegment(const NodeRefSegment&) = default; + NodeRefSegment(NodeRefSegment&&) = default; + + NodeRefSegment& operator=(const NodeRefSegment&) = default; + NodeRefSegment& operator=(NodeRefSegment&&) = default; + + ~NodeRefSegment() = default; + + /// Return first NodeRef of Segment according to sorting order (bottom left to top right). + const osmium::NodeRef& first() const { + return m_first; + } + + /// Return second NodeRef of Segment according to sorting order (bottom left to top right). + const osmium::NodeRef& second() const { + return m_second; + } + + bool to_left_of(const osmium::Location location) const { + // std::cerr << "segment " << first() << "--" << second() << " to_left_of(" << location << "\n"; + + if (first().location() == location || second().location() == location) { + return false; + } + + const std::pair mm = std::minmax(first().location(), second().location(), [](const osmium::Location a, const osmium::Location b) { + return a.y() < b.y(); + }); + + if (mm.first.y() >= location.y() || mm.second.y() < location.y() || first().location().x() > location.x()) { + // std::cerr << " false\n"; + return false; + } + + int64_t ax = mm.first.x(); + int64_t bx = mm.second.x(); + int64_t lx = location.x(); + int64_t ay = mm.first.y(); + int64_t by = mm.second.y(); + int64_t ly = location.y(); + return ((bx - ax)*(ly - ay) - (by - ay)*(lx - ax)) <= 0; + } + + bool role_outer() const { + return !strcmp(m_role, "outer"); + } + + bool role_inner() const { + return !strcmp(m_role, "inner"); + } + + const osmium::Way* way() const { + return m_way; + } + + }; // class NodeRefSegment + + /// NodeRefSegments are equal if both their locations are equal + inline bool operator==(const NodeRefSegment& lhs, const NodeRefSegment& rhs) { + return lhs.first().location() == rhs.first().location() && lhs.second().location() == rhs.second().location(); + } + + inline bool operator!=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) { + return ! (lhs == rhs); + } + + /** + * NodeRefSegments are "smaller" if they are to the left and down of another + * segment. The first() location is checked first() and only if they have the + * same first() location the second() location is taken into account. + */ + inline bool operator<(const NodeRefSegment& lhs, const NodeRefSegment& rhs) { + return (lhs.first().location() == rhs.first().location() && lhs.second().location() < rhs.second().location()) || lhs.first().location() < rhs.first().location(); + } + + inline bool operator>(const NodeRefSegment& lhs, const NodeRefSegment& rhs) { + return rhs < lhs; + } + + inline bool operator<=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) { + return ! (rhs < lhs); + } + + inline bool operator>=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) { + return ! (lhs < rhs); + } + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const NodeRefSegment& segment) { + return out << segment.first() << "--" << segment.second(); + } + + inline bool outside_x_range(const NodeRefSegment& s1, const NodeRefSegment& s2) { + if (s1.first().location().x() > s2.second().location().x()) { + return true; + } + return false; + } + + inline bool y_range_overlap(const NodeRefSegment& s1, const NodeRefSegment& s2) { + auto m1 = std::minmax(s1.first().location().y(), s1.second().location().y()); + auto m2 = std::minmax(s2.first().location().y(), s2.second().location().y()); + if (m1.first > m2.second || m2.first > m1.second) { + return false; + } + return true; + } + + /** + * Calculate the intersection between to NodeRefSegments. The result is returned + * as a Location. Note that because the Location uses integers with limited + * precision internally, the result might be slightly different than the + * numerically correct location. + * + * If the segments touch in one of their endpoints, it doesn't count as an + * intersection. + * + * If the segments intersect not in a single point but in multiple points, ie + * if they overlap, this is NOT detected. + * + * @returns Undefined osmium::Location if there is no intersection or a defined + * Location if the segments intersect. + */ + inline osmium::Location calculate_intersection(const NodeRefSegment& s1, const NodeRefSegment& s2) { + if (s1.first().location() == s2.first().location() || + s1.first().location() == s2.second().location() || + s1.second().location() == s2.first().location() || + s1.second().location() == s2.second().location()) { + return osmium::Location(); + } + + double denom = ((s2.second().lat() - s2.first().lat())*(s1.second().lon() - s1.first().lon())) - + ((s2.second().lon() - s2.first().lon())*(s1.second().lat() - s1.first().lat())); + + if (denom != 0) { + double nume_a = ((s2.second().lon() - s2.first().lon())*(s1.first().lat() - s2.first().lat())) - + ((s2.second().lat() - s2.first().lat())*(s1.first().lon() - s2.first().lon())); + + double nume_b = ((s1.second().lon() - s1.first().lon())*(s1.first().lat() - s2.first().lat())) - + ((s1.second().lat() - s1.first().lat())*(s1.first().lon() - s2.first().lon())); + + if ((denom > 0 && nume_a >= 0 && nume_a <= denom && nume_b >= 0 && nume_b <= denom) || + (denom < 0 && nume_a <= 0 && nume_a >= denom && nume_b <= 0 && nume_b >= denom)) { + double ua = nume_a / denom; + double ix = s1.first().lon() + ua*(s1.second().lon() - s1.first().lon()); + double iy = s1.first().lat() + ua*(s1.second().lat() - s1.first().lat()); + return osmium::Location(ix, iy); + } + } + + return osmium::Location(); + } + + } // namespace detail + + } // namespace area + +} // namespace osmium + +#endif // OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP diff --git a/ThirdParty/osmium/area/detail/proto_ring.hpp b/ThirdParty/osmium/area/detail/proto_ring.hpp new file mode 100644 index 000000000..1dd236d21 --- /dev/null +++ b/ThirdParty/osmium/area/detail/proto_ring.hpp @@ -0,0 +1,274 @@ +#ifndef OSMIUM_AREA_DETAIL_PROTO_RING_HPP +#define OSMIUM_AREA_DETAIL_PROTO_RING_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace area { + + namespace detail { + + /** + * A ring in the process of being built by the Assembler object. + */ + class ProtoRing { + + public: + + typedef std::vector segments_type; + + private: + + // segments in this ring + segments_type m_segments; + + bool m_outer {true}; + + // if this is an outer ring, these point to it's inner rings (if any) + std::vector m_inner; + + public: + + explicit ProtoRing(const NodeRefSegment& segment) : + m_segments() { + add_segment_back(segment); + } + + explicit ProtoRing(segments_type::const_iterator sbegin, segments_type::const_iterator send) : + m_segments(static_cast(std::distance(sbegin, send))) { + std::copy(sbegin, send, m_segments.begin()); + } + + bool outer() const { + return m_outer; + } + + void set_inner() { + m_outer = false; + } + + segments_type& segments() { + return m_segments; + } + + const segments_type& segments() const { + return m_segments; + } + + void remove_segments(segments_type::iterator sbegin, segments_type::iterator send) { + m_segments.erase(sbegin, send); + } + + void add_segment_front(const NodeRefSegment& segment) { + m_segments.insert(m_segments.begin(), segment); + } + + void add_segment_back(const NodeRefSegment& segment) { + m_segments.push_back(segment); + } + + const NodeRefSegment& get_segment_front() const { + return m_segments.front(); + } + + NodeRefSegment& get_segment_front() { + return m_segments.front(); + } + + const NodeRefSegment& get_segment_back() const { + return m_segments.back(); + } + + NodeRefSegment& get_segment_back() { + return m_segments.back(); + } + + bool closed() const { + return m_segments.front().first().location() == m_segments.back().second().location(); + } + + int64_t sum() const { + int64_t sum = 0; + + for (const auto& segment : m_segments) { + sum += static_cast(segment.first().location().x()) * static_cast(segment.second().location().y()) - + static_cast(segment.second().location().x()) * static_cast(segment.first().location().y()); + } + + return sum; + } + + bool is_cw() const { + return sum() <= 0; + } + + int64_t area() const { + return std::abs(sum()) / 2; + } + + void swap_segments(ProtoRing& other) { + std::swap(m_segments, other.m_segments); + } + + void add_inner_ring(ProtoRing* ring) { + m_inner.push_back(ring); + } + + const std::vector inner_rings() const { + return m_inner; + } + + void print(std::ostream& out) const { + out << "["; + bool first = true; + for (const auto& segment : m_segments) { + if (first) { + out << segment.first().ref(); + } + out << ',' << segment.second().ref(); + first = false; + } + out << "]"; + } + + void reverse() { + std::for_each(m_segments.begin(), m_segments.end(), [](NodeRefSegment& segment) { + segment.swap_locations(); + }); + std::reverse(m_segments.begin(), m_segments.end()); + } + + /** + * Merge other ring to end of this ring. + */ + void merge_ring(const ProtoRing& other, bool debug) { + if (debug) { + std::cerr << " MERGE rings "; + print(std::cerr); + std::cerr << " to "; + other.print(std::cerr); + std::cerr << "\n"; + } + m_segments.insert(m_segments.end(), other.m_segments.begin(), other.m_segments.end()); + if (debug) { + std::cerr << " result ring: "; + print(std::cerr); + std::cerr << "\n"; + } + } + + void merge_ring_reverse(const ProtoRing& other, bool debug) { + if (debug) { + std::cerr << " MERGE rings (reverse) "; + print(std::cerr); + std::cerr << " to "; + other.print(std::cerr); + std::cerr << "\n"; + } + size_t n = m_segments.size(); + m_segments.resize(n + other.m_segments.size()); + std::transform(other.m_segments.rbegin(), other.m_segments.rend(), m_segments.begin() + static_cast(n), [](NodeRefSegment segment) { + segment.swap_locations(); + return segment; + }); + if (debug) { + std::cerr << " result ring: "; + print(std::cerr); + std::cerr << "\n"; + } + } + + const NodeRef& min_node() const { + auto it = std::min_element(m_segments.begin(), m_segments.end()); + if (location_less()(it->first(), it->second())) { + return it->first(); + } else { + return it->second(); + } + } + + bool is_in(ProtoRing* outer) { + osmium::Location testpoint = segments().front().first().location(); + bool is_in = false; + + for (size_t i = 0, j = outer->segments().size()-1; i < outer->segments().size(); j = i++) { + if (((outer->segments()[i].first().location().y() > testpoint.y()) != (outer->segments()[j].first().location().y() > testpoint.y())) && + (testpoint.x() < (outer->segments()[j].first().location().x() - outer->segments()[i].first().location().x()) * (testpoint.y() - outer->segments()[i].first().location().y()) / (outer->segments()[j].first().location().y() - outer->segments()[i].first().location().y()) + outer->segments()[i].first().location().x()) ) { + is_in = !is_in; + } + } + + return is_in; + } + + void get_ways(std::set& ways) { + for (const auto& segment : m_segments) { + ways.insert(segment.way()); + } + } + + bool contains(const NodeRefSegment& segment) const { + for (const auto& s : m_segments) { + if (s == segment || (s.first() == segment.second() && s.second() == segment.first())) { + return true; + } + } + return false; + } + + }; // class ProtoRing + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const ProtoRing& ring) { + ring.print(out); + return out; + } + + } // namespace detail + + } // namespace area + +} // namespace osmium + +#endif // OSMIUM_AREA_DETAIL_PROTO_RING_HPP diff --git a/ThirdParty/osmium/area/detail/segment_list.hpp b/ThirdParty/osmium/area/detail/segment_list.hpp new file mode 100644 index 000000000..dcee3d00a --- /dev/null +++ b/ThirdParty/osmium/area/detail/segment_list.hpp @@ -0,0 +1,216 @@ +#ifndef OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP +#define OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace osmium { + + namespace area { + + namespace detail { + + /** + * This is a helper class for the area assembler. It models + * a list of segments. + */ + class SegmentList { + + typedef std::vector slist_type; + + slist_type m_segments; + + bool m_debug; + + public: + + explicit SegmentList(bool debug) : + m_debug(debug) { + } + + ~SegmentList() = default; + + SegmentList(const SegmentList& other) = delete; + SegmentList(SegmentList&& other) = delete; + + SegmentList& operator=(const SegmentList& other) = delete; + SegmentList& operator=(SegmentList&& other) = delete; + + /// The number of segments in the list. + size_t size() const { + return m_segments.size(); + } + + bool empty() const { + return m_segments.empty(); + } + + typedef slist_type::const_iterator const_iterator; + + const_iterator begin() const { + return m_segments.begin(); + } + + const_iterator end() const { + return m_segments.end(); + } + + /** + * Enable or disable debug output to stderr. This is for Osmium + * developers only. + */ + void enable_debug_output(bool debug=true) { + m_debug = debug; + } + + /// Clear the list of segments. All segments are removed. + void clear() { + m_segments.clear(); + } + + /// Sort the list of segments. + void sort() { + std::sort(m_segments.begin(), m_segments.end()); + } + + /** + * Extract segments from given way and add them to the list. + * + * Segments connecting two nodes with the same location (ie same + * node or different node with same location) are removed. + * + * XXX should two nodes with same location be reported? + */ + void extract_segments_from_way(const osmium::Way& way, const char* role) { + osmium::NodeRef last_nr; + for (const osmium::NodeRef& nr : way.nodes()) { + if (last_nr.location() && last_nr.location() != nr.location()) { + m_segments.emplace_back(last_nr, nr, role, &way); + } + last_nr = nr; + } + } + + /** + * Extract all segments from all ways that make up this + * multipolygon relation and add them to the list. + */ + void extract_segments_from_ways(const osmium::Relation& relation, const std::vector& members, const osmium::memory::Buffer& in_buffer) { + auto member_it = relation.members().begin(); + for (size_t offset : members) { + const osmium::Way& way = in_buffer.get(offset); + extract_segments_from_way(way, member_it->role()); + ++member_it; + } + } + + /** + * Find duplicate segments (ie same start and end point) in the + * list and remove them. This will always remove pairs of the same + * segment. So if there are three, for instance, two will be + * removed and one will be left. + */ + void erase_duplicate_segments() { + while (true) { + auto it = std::adjacent_find(m_segments.begin(), m_segments.end()); + if (it == m_segments.end()) { + return; + } + if (m_debug) { + std::cerr << " erase duplicate segment: " << *it << "\n"; + } + m_segments.erase(it, it+2); + } + } + + /** + * Find intersection between segments. + * + * @param problem_reporter Any intersections found are reported to this object. + * @returns true if there are intersections. + */ + bool find_intersections(osmium::area::ProblemReporter* problem_reporter) const { + if (m_segments.empty()) { + return false; + } + + bool found_intersections = false; + + for (auto it1 = m_segments.begin(); it1 != m_segments.end()-1; ++it1) { + const NodeRefSegment& s1 = *it1; + for (auto it2 = it1+1; it2 != m_segments.end(); ++it2) { + const NodeRefSegment& s2 = *it2; + + assert(s1 != s2); // erase_duplicate_segments() should have made sure of that + + if (outside_x_range(s2, s1)) { + break; + } + + if (y_range_overlap(s1, s2)) { + osmium::Location intersection = calculate_intersection(s1, s2); + if (intersection) { + found_intersections = true; + if (m_debug) { + std::cerr << " segments " << s1 << " and " << s2 << " intersecting at " << intersection << "\n"; + } + if (problem_reporter) { + problem_reporter->report_intersection(s1.way()->id(), s1.first().location(), s1.second().location(), s2.way()->id(), s2.first().location(), s2.second().location(), intersection); + } + } + } + } + } + + return found_intersections; + } + + }; // class SegmentList + + } // namespace detail + + } // namespace area + +} // namespace osmium + +#endif // OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP diff --git a/ThirdParty/osmium/area/multipolygon_collector.hpp b/ThirdParty/osmium/area/multipolygon_collector.hpp new file mode 100644 index 000000000..24aa89c48 --- /dev/null +++ b/ThirdParty/osmium/area/multipolygon_collector.hpp @@ -0,0 +1,211 @@ +#ifndef OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP +#define OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + struct invalid_location; + + namespace relations { + class RelationMeta; + } + + /** + * @brief Code related to the building of areas (multipolygons) from relations. + */ + namespace area { + + /** + * This class collects all data needed for creating areas from + * relations tagged with type=multipolygon or type=boundary. + * Most of its functionality is derived from the parent class + * osmium::relations::Collector. + * + * The actual assembling of the areas is done by the assembler + * class given as template argument. + * + * @tparam TAssembler Multipolygon Assembler class. + */ + template + class MultipolygonCollector : public osmium::relations::Collector, false, true, false> { + + typedef typename osmium::relations::Collector, false, true, false> collector_type; + + typedef typename TAssembler::config_type assembler_config_type; + const assembler_config_type m_assembler_config; + + osmium::memory::Buffer m_output_buffer; + + static constexpr size_t initial_output_buffer_size = 1024 * 1024; + static constexpr size_t max_buffer_size_for_flush = 100 * 1024; + + void flush_output_buffer() { + if (this->callback()) { + this->callback()(m_output_buffer); + m_output_buffer.clear(); + } + } + + void possibly_flush_output_buffer() { + if (m_output_buffer.committed() > max_buffer_size_for_flush) { + flush_output_buffer(); + } + } + + public: + + explicit MultipolygonCollector(const assembler_config_type& assembler_config) : + collector_type(), + m_assembler_config(assembler_config), + m_output_buffer(initial_output_buffer_size, osmium::memory::Buffer::auto_grow::yes) { + } + + /** + * We are interested in all relations tagged with type=multipolygon or + * type=boundary. + * + * Overwritten from the base class. + */ + bool keep_relation(const osmium::Relation& relation) const { + const char* type = relation.tags().get_value_by_key("type"); + + // ignore relations without "type" tag + if (!type) { + return false; + } + + if ((!strcmp(type, "multipolygon")) || (!strcmp(type, "boundary"))) { + return true; + } + + return false; + } + + /** + * Overwritten from the base class. + */ + bool keep_member(const osmium::relations::RelationMeta& /*relation_meta*/, const osmium::RelationMember& member) const { + // We are only interested in members of type way. + return member.type() == osmium::item_type::way; + } + + /** + * This is called when a way is not in any multipolygon + * relation. + * + * Overwritten from the base class. + */ + void way_not_in_any_relation(const osmium::Way& way) { + if (way.ends_have_same_location() && way.nodes().size() > 3) { + // way is closed and has enough nodes, build simple multipolygon + try { + TAssembler assembler(m_assembler_config); + assembler(way, m_output_buffer); + possibly_flush_output_buffer(); + } catch (osmium::invalid_location&) { + // XXX ignore + } + } + } + + void complete_relation(osmium::relations::RelationMeta& relation_meta) { + const osmium::Relation& relation = this->get_relation(relation_meta); + std::vector offsets; + for (const auto& member : relation.members()) { + if (member.ref() != 0) { + offsets.push_back(this->get_offset(member.type(), member.ref())); + } + } + try { + TAssembler assembler(m_assembler_config); + assembler(relation, offsets, this->members_buffer(), m_output_buffer); + possibly_flush_output_buffer(); + } catch (osmium::invalid_location&) { + // XXX ignore + } + + // clear member metas + for (const auto& member : relation.members()) { + if (member.ref() != 0) { + auto& mmv = this->member_meta(member.type()); + auto range = std::equal_range(mmv.begin(), mmv.end(), osmium::relations::MemberMeta(member.ref())); + assert(range.first != range.second); + + // if this is the last time this object was needed + // then mark it as removed + if (range.first + 1 == range.second) { + this->get_member(range.first->buffer_offset()).removed(true); + } + + for (auto it = range.first; it != range.second; ++it) { + if (relation.id() == this->get_relation(it->relation_pos()).id()) { + mmv.erase(it); + break; + } + } + } + } + } + + void flush() { + flush_output_buffer(); + } + + osmium::memory::Buffer read() { + osmium::memory::Buffer buffer(initial_output_buffer_size, osmium::memory::Buffer::auto_grow::yes); + std::swap(buffer, m_output_buffer); + return buffer; + } + + }; // class MultipolygonCollector + + } // namespace area + +} // namespace osmium + +#endif // OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP diff --git a/ThirdParty/osmium/area/problem_reporter.hpp b/ThirdParty/osmium/area/problem_reporter.hpp new file mode 100644 index 000000000..9e3eece8d --- /dev/null +++ b/ThirdParty/osmium/area/problem_reporter.hpp @@ -0,0 +1,149 @@ +#ifndef OSMIUM_AREA_PROBLEM_REPORTER_HPP +#define OSMIUM_AREA_PROBLEM_REPORTER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +namespace osmium { + + namespace area { + + /** + * When assembling a multipolygon/area from a multipolygon relation + * or a closed way several problems can be detected. This includes + * intersections between lines, wrong role attributes on relation + * members etc. These problems are reported by the area::Assembler + * class to the ProblemReporter class or one of its child classes. + * + * This is the parent class which does nothing with the reports. + * Child classes are expected to implement different ways of + * reporting the problems. + */ + class ProblemReporter { + + protected: + + // Type of object we are currently working on + osmium::item_type m_object_type; + + // ID of the relation/way we are currently working on + osmium::object_id_type m_object_id; + + public: + + ProblemReporter() = default; + + virtual ~ProblemReporter() = default; + + /** + * Set the object the next problem reports will be on. + * + * @param object_type The type of the object. + * @param object_id The ID of the object. + */ + void set_object(osmium::item_type object_type, osmium::object_id_type object_id) { + m_object_type = object_type; + m_object_id = object_id; + } + +// Disable "unused-parameter" warning, so that the compiler will not complain. +// We can't remove the parameter names, because then doxygen will complain. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" + + /** + * Report a duplicate node, ie. two nodes with the same location. + * + * @param node_id1 ID of the first node. + * @param node_id2 ID of the second node. + * @param location Location of both nodes. + */ + virtual void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) { + } + + /** + * Report an intersection between two segments. + * + * @param way1_id ID of the first involved way. + * @param way1_seg_start Location where the segment of the first way with the intersection starts + * @param way1_seg_end Location where the segment of the first way with the intersection ends + * @param way2_id ID of the second involved way. + * @param way2_seg_start Location where the segment of the second way with the intersection starts + * @param way2_seg_end Location where the segment of the second way with the intersection ends + * @param intersection Location of the intersection. This might be slightly off the correct location due to rounding. + */ + virtual void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end, + osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) { + } + + /** + * Report an open ring. + * + * @param end1 Location of the first open end. + * @param end2 Location of the second open end. + */ + virtual void report_ring_not_closed(osmium::Location end1, osmium::Location end2) { + } + + /** + * Report a segment that should have role "outer", but has a different role. + * + * @param way_id ID of the way this segment is in. + * @param seg_start Start of the segment with the wrong role. + * @param seg_end End of the segment with the wrong role. + */ + virtual void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) { + } + + /** + * Report a segment that should have role "inner", but has a different role. + * + * @param way_id ID of the way this segment is in. + * @param seg_start Start of the segment with the wrong role. + * @param seg_end End of the segment with the wrong role. + */ + virtual void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) { + } + +#pragma GCC diagnostic pop + + }; // class ProblemReporter + + } // namespace area + +} // namespace osmium + +#endif // OSMIUM_AREA_PROBLEM_REPORTER_HPP diff --git a/ThirdParty/osmium/area/problem_reporter_exception.hpp b/ThirdParty/osmium/area/problem_reporter_exception.hpp new file mode 100644 index 000000000..eebc553a8 --- /dev/null +++ b/ThirdParty/osmium/area/problem_reporter_exception.hpp @@ -0,0 +1,96 @@ +#ifndef OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP +#define OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include +#include +#include + +namespace osmium { + + namespace area { + + class ProblemReporterException : public ProblemReporterStream { + + std::stringstream m_sstream; + + public: + + ProblemReporterException() : + ProblemReporterStream(m_sstream) { + } + + virtual ~ProblemReporterException() = default; + + void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override { + m_sstream.str(); + ProblemReporterStream::report_duplicate_node(node_id1, node_id2, location); + throw std::runtime_error(m_sstream.str()); + } + + void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end, + osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override { + m_sstream.str(); + ProblemReporterStream::report_intersection(way1_id, way1_seg_start, way1_seg_end, way2_id, way2_seg_start, way2_seg_end, intersection); + throw std::runtime_error(m_sstream.str()); + } + + void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override { + m_sstream.str(); + ProblemReporterStream::report_ring_not_closed(end1, end2); + throw std::runtime_error(m_sstream.str()); + } + + void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { + m_sstream.str(); + ProblemReporterStream::report_role_should_be_outer(way_id, seg_start, seg_end); + throw std::runtime_error(m_sstream.str()); + } + + void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { + m_sstream.str(); + ProblemReporterStream::report_role_should_be_inner(way_id, seg_start, seg_end); + throw std::runtime_error(m_sstream.str()); + } + + }; // class ProblemReporterException + + } // namespace area + +} // namespace osmium + +#endif // OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP diff --git a/ThirdParty/osmium/area/problem_reporter_ogr.hpp b/ThirdParty/osmium/area/problem_reporter_ogr.hpp new file mode 100644 index 000000000..f1bcf87ac --- /dev/null +++ b/ThirdParty/osmium/area/problem_reporter_ogr.hpp @@ -0,0 +1,202 @@ +#ifndef OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP +#define OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#define OSMIUM_COMPILE_WITH_CFLAGS_OGR `gdal-config --cflags` +#define OSMIUM_LINK_WITH_LIBS_OGR `gdal-config --libs` + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wredundant-decls" +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" +# include +# include +#pragma GCC diagnostic pop + +#include +#include + +#include +#include +#include +#include + +namespace osmium { + + namespace area { + + /** + * Report problems when assembling areas by adding them to + * layers in an OGR datasource. + */ + class ProblemReporterOGR : public ProblemReporter { + + osmium::geom::OGRFactory<> m_ogr_factory; + + OGRDataSource* m_data_source; + + OGRLayer* m_layer_perror; + OGRLayer* m_layer_lerror; + + void write_point(const char* problem_type, osmium::object_id_type id1, osmium::object_id_type id2, osmium::Location location) { + OGRFeature* feature = OGRFeature::CreateFeature(m_layer_perror->GetLayerDefn()); + std::unique_ptr ogr_point = m_ogr_factory.create_point(location); + feature->SetGeometry(ogr_point.get()); + feature->SetField("id1", static_cast(id1)); + feature->SetField("id2", static_cast(id2)); + feature->SetField("problem_type", problem_type); + + if (m_layer_perror->CreateFeature(feature) != OGRERR_NONE) { + std::runtime_error("Failed to create feature on layer 'perrors'"); + } + + OGRFeature::DestroyFeature(feature); + } + + void write_line(const char* problem_type, osmium::object_id_type id1, osmium::object_id_type id2, osmium::Location loc1, osmium::Location loc2) { + std::unique_ptr ogr_point1 = m_ogr_factory.create_point(loc1); + std::unique_ptr ogr_point2 = m_ogr_factory.create_point(loc2); + std::unique_ptr ogr_linestring = std::unique_ptr(new OGRLineString()); + ogr_linestring->addPoint(ogr_point1.get()); + ogr_linestring->addPoint(ogr_point2.get()); + OGRFeature* feature = OGRFeature::CreateFeature(m_layer_lerror->GetLayerDefn()); + feature->SetGeometry(ogr_linestring.get()); + feature->SetField("id1", static_cast(id1)); + feature->SetField("id2", static_cast(id2)); + feature->SetField("problem_type", problem_type); + + if (m_layer_lerror->CreateFeature(feature) != OGRERR_NONE) { + std::runtime_error("Failed to create feature on layer 'lerrors'"); + } + + OGRFeature::DestroyFeature(feature); + } + + public: + + explicit ProblemReporterOGR(OGRDataSource* data_source) : + m_data_source(data_source) { + + OGRSpatialReference sparef; + sparef.SetWellKnownGeogCS("WGS84"); + + m_layer_perror = m_data_source->CreateLayer("perrors", &sparef, wkbPoint, nullptr); + if (!m_layer_perror) { + std::runtime_error("Layer creation failed for layer 'perrors'"); + } + + OGRFieldDefn layer_perror_field_id1("id1", OFTReal); + layer_perror_field_id1.SetWidth(10); + + if (m_layer_perror->CreateField(&layer_perror_field_id1) != OGRERR_NONE) { + std::runtime_error("Creating field 'id1' failed for layer 'perrors'"); + } + + OGRFieldDefn layer_perror_field_id2("id2", OFTReal); + layer_perror_field_id2.SetWidth(10); + + if (m_layer_perror->CreateField(&layer_perror_field_id2) != OGRERR_NONE) { + std::runtime_error("Creating field 'id2' failed for layer 'perrors'"); + } + + OGRFieldDefn layer_perror_field_problem_type("problem_type", OFTString); + layer_perror_field_problem_type.SetWidth(30); + + if (m_layer_perror->CreateField(&layer_perror_field_problem_type) != OGRERR_NONE) { + std::runtime_error("Creating field 'problem_type' failed for layer 'perrors'"); + } + + /**************/ + + m_layer_lerror = m_data_source->CreateLayer("lerrors", &sparef, wkbLineString, nullptr); + if (!m_layer_lerror) { + std::runtime_error("Layer creation failed for layer 'lerrors'"); + } + + OGRFieldDefn layer_lerror_field_id1("id1", OFTReal); + layer_lerror_field_id1.SetWidth(10); + + if (m_layer_lerror->CreateField(&layer_lerror_field_id1) != OGRERR_NONE) { + std::runtime_error("Creating field 'id1' failed for layer 'lerrors'"); + } + + OGRFieldDefn layer_lerror_field_id2("id2", OFTReal); + layer_lerror_field_id2.SetWidth(10); + + if (m_layer_lerror->CreateField(&layer_lerror_field_id2) != OGRERR_NONE) { + std::runtime_error("Creating field 'id2' failed for layer 'lerrors'"); + } + + OGRFieldDefn layer_lerror_field_problem_type("problem_type", OFTString); + layer_lerror_field_problem_type.SetWidth(30); + + if (m_layer_lerror->CreateField(&layer_lerror_field_problem_type) != OGRERR_NONE) { + std::runtime_error("Creating field 'problem_type' failed for layer 'lerrors'"); + } + } + + virtual ~ProblemReporterOGR() = default; + + void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override { + write_point("duplicate_node", node_id1, node_id2, location); + } + + void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end, + osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override { + write_point("intersection", m_object_id, 0, intersection); + write_line("intersection", m_object_id, way1_id, way1_seg_start, way1_seg_end); + write_line("intersection", m_object_id, way2_id, way2_seg_start, way2_seg_end); + } + + void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override { + write_point("ring_not_closed", m_object_id, 0, end1); + write_point("ring_not_closed", m_object_id, 0, end2); + } + + void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { + write_line("role_should_be_outer", m_object_id, way_id, seg_start, seg_end); + } + + void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { + write_line("role_should_be_inner", m_object_id, way_id, seg_start, seg_end); + } + + }; // class ProblemReporterOGR + + } // namespace area + +} // namespace osmium + +#endif // OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP diff --git a/ThirdParty/osmium/area/problem_reporter_stream.hpp b/ThirdParty/osmium/area/problem_reporter_stream.hpp new file mode 100644 index 000000000..3ff2f20bb --- /dev/null +++ b/ThirdParty/osmium/area/problem_reporter_stream.hpp @@ -0,0 +1,96 @@ +#ifndef OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP +#define OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +#include +#include +#include +#include + +namespace osmium { + + namespace area { + + class ProblemReporterStream : public ProblemReporter { + + std::ostream& m_out; + + public: + + explicit ProblemReporterStream(std::ostream& out) : + m_out(out) { + } + + virtual ~ProblemReporterStream() = default; + + void header(const char* msg) { + m_out << "DATA PROBLEM: " << msg << " on " << item_type_to_char(m_object_type) << m_object_id << ": "; + } + + void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override { + header("duplicate node"); + m_out << "node_id1=" << node_id1 << " node_id2=" << node_id2 << " location=" << location << "\n"; + } + + void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end, + osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override { + header("intersection"); + m_out << "way1_id=" << way1_id << " way1_seg_start=" << way1_seg_start << " way1_seg_end=" << way1_seg_end + << " way2_id=" << way2_id << " way2_seg_start=" << way2_seg_start << " way2_seg_end=" << way2_seg_end << " intersection=" << intersection << "\n"; + } + + void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override { + header("ring not closed"); + m_out << "end1=" << end1 << " end2=" << end2 << "\n"; + } + + void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { + header("role should be outer"); + m_out << "way_id=" << way_id << " seg_start=" << seg_start << " seg_end=" << seg_end << "\n"; + } + + void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override { + header("role should be inner"); + m_out << "way_id=" << way_id << " seg_start=" << seg_start << " seg_end=" << seg_end << "\n"; + } + + }; // class ProblemReporterStream + + } // namespace area + +} // namespace osmium + +#endif // OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP diff --git a/ThirdParty/osmium/builder/builder.hpp b/ThirdParty/osmium/builder/builder.hpp new file mode 100644 index 000000000..bd762be2c --- /dev/null +++ b/ThirdParty/osmium/builder/builder.hpp @@ -0,0 +1,179 @@ +#ifndef OSMIUM_BUILDER_BUILDER_HPP +#define OSMIUM_BUILDER_BUILDER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + /** + * @brief Classes for building OSM objects and other items in buffers + */ + namespace builder { + + class Builder { + + osmium::memory::Buffer& m_buffer; + Builder* m_parent; + size_t m_item_offset; + + Builder(const Builder&) = delete; + Builder(Builder&&) = delete; + + Builder& operator=(const Builder&) = delete; + Builder& operator=(Builder&&) = delete; + + protected: + + explicit Builder(osmium::memory::Buffer& buffer, Builder* parent, size_t size) : + m_buffer(buffer), + m_parent(parent), + m_item_offset(buffer.written()) { + m_buffer.reserve_space(size); + assert(buffer.is_aligned()); + if (m_parent) { + m_parent->add_size(size); + } + } + + ~Builder() = default; + + osmium::memory::Item& item() const { + return *reinterpret_cast(m_buffer.data() + m_item_offset); + } + + public: + + /** + * Add padding to buffer (if needed) to align data properly. + * + * This calculates how many padding bytes are needed and adds + * as many zero bytes to the buffer. It also adds this number + * to the size of the current item (if the "self" param is + * true) and recursively to all the parent items. + * + * @param self If true add number of padding bytes to size + * of current item. Size is always added to + * parent item (if any). + * + */ + void add_padding(bool self=false) { + size_t padding = osmium::memory::align_bytes - (size() % osmium::memory::align_bytes); + if (padding != osmium::memory::align_bytes) { + std::memset(m_buffer.reserve_space(padding), 0, padding); + if (self) { + add_size(padding); + } else if (m_parent) { + m_parent->add_size(padding); + assert(m_parent->size() % osmium::memory::align_bytes == 0); + } + } + } + + void add_size(uint32_t size) { + item().add_size(size); + if (m_parent) { + m_parent->add_size(size); + } + } + + uint32_t size() const { + return item().byte_size(); + } + + void add_item(const osmium::memory::Item* item) { + std::memcpy(m_buffer.reserve_space(item->padded_size()), item, item->padded_size()); + add_size(item->padded_size()); + } + + /** + * Reserve space for an object of class T in buffer and return + * pointer to it. + */ + template + T* reserve_space_for() { + assert(m_buffer.is_aligned()); + return reinterpret_cast(m_buffer.reserve_space(sizeof(T))); + } + + /** + * Append \0-terminated string to buffer. + */ + size_t append(const char* str) { + size_t length = std::strlen(str) + 1; + std::memcpy(m_buffer.reserve_space(length), str, length); + return length; + } + + /// Return the buffer this builder is using. + osmium::memory::Buffer& buffer() { + return m_buffer; + } + + }; // class Builder + + template + class ObjectBuilder : public Builder { + + public: + + explicit ObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + Builder(buffer, parent, sizeof(T)) { + new (&item()) T(); + } + + T& object() { + return static_cast(item()); + } + + void add_user(const char* user) { + object().user_size(std::strlen(user) + 1); + add_size(append(user)); + add_padding(true); + } + + }; // class ObjectBuilder + + } // namespace builder + +} // namespace osmium + +#endif // OSMIUM_BUILDER_BUILDER_HPP diff --git a/ThirdParty/osmium/builder/builder_helper.hpp b/ThirdParty/osmium/builder/builder_helper.hpp new file mode 100644 index 000000000..3e00f81c4 --- /dev/null +++ b/ThirdParty/osmium/builder/builder_helper.hpp @@ -0,0 +1,103 @@ +#ifndef OSMIUM_BUILDER_BUILDER_HELPER_HPP +#define OSMIUM_BUILDER_BUILDER_HELPER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + class NodeRef; + class TagList; + class WayNodeList; + + namespace builder { + + inline const osmium::WayNodeList& build_way_node_list(osmium::memory::Buffer& buffer, const std::initializer_list& nodes) { + size_t pos = buffer.committed(); + { + osmium::builder::WayNodeListBuilder wnl_builder(buffer); + for (const auto& node_ref : nodes) { + wnl_builder.add_node_ref(node_ref); + } + } + buffer.commit(); + return buffer.get(pos); + } + + inline const osmium::TagList& build_tag_list(osmium::memory::Buffer& buffer, const std::initializer_list>& tags) { + size_t pos = buffer.committed(); + { + osmium::builder::TagListBuilder tl_builder(buffer); + for (const auto& p : tags) { + tl_builder.add_tag(p.first, p.second); + } + } + buffer.commit(); + return buffer.get(pos); + } + + inline const osmium::TagList& build_tag_list_from_map(osmium::memory::Buffer& buffer, const std::map& tags) { + size_t pos = buffer.committed(); + { + osmium::builder::TagListBuilder tl_builder(buffer); + for (const auto& p : tags) { + tl_builder.add_tag(p.first, p.second); + } + } + buffer.commit(); + return buffer.get(pos); + } + + inline const osmium::TagList& build_tag_list_from_func(osmium::memory::Buffer& buffer, std::function func) { + size_t pos = buffer.committed(); + { + osmium::builder::TagListBuilder tl_builder(buffer); + func(tl_builder); + } + buffer.commit(); + return buffer.get(pos); + } + + } // namespace builder + +} // namespace osmium + +#endif // OSMIUM_BUILDER_BUILDER_HELPER_HPP diff --git a/ThirdParty/osmium/builder/osm_object_builder.hpp b/ThirdParty/osmium/builder/osm_object_builder.hpp new file mode 100644 index 000000000..0fb26c8ae --- /dev/null +++ b/ThirdParty/osmium/builder/osm_object_builder.hpp @@ -0,0 +1,207 @@ +#ifndef OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP +#define OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace memory { + class Buffer; + } + + namespace builder { + + class TagListBuilder : public ObjectBuilder { + + public: + + explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + ObjectBuilder(buffer, parent) { + } + + ~TagListBuilder() { + add_padding(); + } + + void add_tag(const char* key, const char* value) { + add_size(append(key) + append(value)); + } + + }; // class TagListBuilder + + template + class NodeRefListBuilder : public ObjectBuilder { + + public: + + explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + ObjectBuilder(buffer, parent) { + } + + ~NodeRefListBuilder() { + static_cast(this)->add_padding(); + } + + void add_node_ref(const NodeRef& node_ref) { + new (static_cast(this)->reserve_space_for()) osmium::NodeRef(node_ref); + static_cast(this)->add_size(sizeof(osmium::NodeRef)); + } + + void add_node_ref(const object_id_type ref, const osmium::Location location=Location()) { + add_node_ref(NodeRef(ref, location)); + } + + }; // class NodeRefListBuilder + + typedef NodeRefListBuilder WayNodeListBuilder; + typedef NodeRefListBuilder OuterRingBuilder; + typedef NodeRefListBuilder InnerRingBuilder; + + class RelationMemberListBuilder : public ObjectBuilder { + + void add_role(osmium::RelationMember* member, const char* role) { + size_t length = std::strlen(role) + 1; + assert(length < std::numeric_limits::max()); + member->set_role_size(static_cast(length)); + add_size(append(role)); + add_padding(true); + } + + public: + + explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + ObjectBuilder(buffer, parent) { + } + + ~RelationMemberListBuilder() { + add_padding(); + } + + void add_member(osmium::item_type type, object_id_type ref, const char* role, const osmium::OSMObject* full_member = nullptr) { + osmium::RelationMember* member = reserve_space_for(); + new (member) osmium::RelationMember(ref, type, full_member != nullptr); + add_size(sizeof(RelationMember)); + add_role(member, role); + if (full_member) { + add_item(full_member); + } + } + + }; // class RelationMemberListBuilder + + template + class OSMObjectBuilder : public ObjectBuilder { + + public: + + explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + ObjectBuilder(buffer, parent) { + static_cast(this)->reserve_space_for(); + static_cast(this)->add_size(sizeof(string_size_type)); + } + + void add_tags(const std::initializer_list>& tags) { + osmium::builder::TagListBuilder tl_builder(static_cast(this)->buffer(), this); + for (const auto& p : tags) { + tl_builder.add_tag(p.first, p.second); + } + } + + }; // class OSMObjectBuilder + + typedef OSMObjectBuilder NodeBuilder; + typedef OSMObjectBuilder RelationBuilder; + + class WayBuilder : public OSMObjectBuilder { + + public: + + explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + OSMObjectBuilder(buffer, parent) { + } + + void add_node_refs(const std::initializer_list& nodes) { + osmium::builder::WayNodeListBuilder builder(buffer(), this); + for (const auto& node_ref : nodes) { + builder.add_node_ref(node_ref); + } + } + + }; // class WayBuilder + + class AreaBuilder : public OSMObjectBuilder { + + public: + + explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) : + OSMObjectBuilder(buffer, parent) { + } + + /** + * Initialize area attributes from the attributes of the given object. + */ + void initialize_from_object(const osmium::OSMObject& source) { + osmium::Area& area = object(); + area.id(osmium::object_id_to_area_id(source.id(), source.type())); + area.version(source.version()); + area.changeset(source.changeset()); + area.timestamp(source.timestamp()); + area.visible(source.visible()); + area.uid(source.uid()); + + add_user(source.user()); + } + + }; // class AreaBuilder + + typedef ObjectBuilder ChangesetBuilder; + + } // namespace builder + +} // namespace osmium + +#endif // OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP diff --git a/ThirdParty/osmium/config/constexpr.hpp b/ThirdParty/osmium/config/constexpr.hpp new file mode 100644 index 000000000..3eddc84a2 --- /dev/null +++ b/ThirdParty/osmium/config/constexpr.hpp @@ -0,0 +1,43 @@ +#ifndef OSMIUM_CONFIG_CONSTEXPR_HPP +#define OSMIUM_CONFIG_CONSTEXPR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +// Workaround for MSVC which doesn't support constexpr in all cases yet +#ifdef _MSC_VER +# define OSMIUM_CONSTEXPR +#else +# define OSMIUM_CONSTEXPR constexpr +#endif + +#endif // OSMIUM_CONFIG_CONSTEXPR_HPP diff --git a/ThirdParty/osmium/diff_handler.hpp b/ThirdParty/osmium/diff_handler.hpp new file mode 100644 index 000000000..986ee1819 --- /dev/null +++ b/ThirdParty/osmium/diff_handler.hpp @@ -0,0 +1,67 @@ +#ifndef OSMIUM_DIFF_HANDLER_HPP +#define OSMIUM_DIFF_HANDLER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +namespace osmium { + + /** + * @brief Osmium diff handlers provide access to differences between OSM object versions + */ + namespace diff_handler { + + class DiffHandler { + + public: + + DiffHandler() { + } + + void node(const osmium::DiffNode&) const { + } + + void way(const osmium::DiffWay&) const { + } + + void relation(const osmium::DiffRelation&) const { + } + + }; // class DiffHandler + + } // namespace diff_handler + +} // namespace osmium + +#endif // OSMIUM_DIFF_HANDLER_HPP diff --git a/ThirdParty/osmium/diff_iterator.hpp b/ThirdParty/osmium/diff_iterator.hpp new file mode 100644 index 000000000..3c485eba4 --- /dev/null +++ b/ThirdParty/osmium/diff_iterator.hpp @@ -0,0 +1,129 @@ +#ifndef OSMIUM_DIFF_ITERATOR_HPP +#define OSMIUM_DIFF_ITERATOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include + +namespace osmium { + + class OSMObject; + + template + class DiffIterator : public std::iterator { + + static_assert(std::is_base_of::value, "TBasicIterator::value_type must derive from osmium::OSMObject"); + + TBasicIterator m_prev; + TBasicIterator m_curr; + TBasicIterator m_next; + + const TBasicIterator m_end; + + mutable osmium::DiffObject m_diff; + + void set_diff() const { + assert(m_curr != m_end); + + TBasicIterator prev = m_prev; + if (prev->type() != m_curr->type() || prev->id() != m_curr->id()) { + prev = m_curr; + } + + TBasicIterator next = m_next; + if (next == m_end || next->type() != m_curr->type() || next->id() != m_curr->id()) { + next = m_curr; + } + + m_diff = osmium::DiffObject(*prev, *m_curr, *next); + } + + public: + + explicit DiffIterator(TBasicIterator begin, TBasicIterator end) : + m_prev(begin), + m_curr(begin), + m_next(begin == end ? begin : ++begin), + m_end(end) { + } + + DiffIterator(const DiffIterator& other) = default; + DiffIterator& operator=(const DiffIterator& other) = default; + + DiffIterator(DiffIterator&& other) = default; + DiffIterator& operator=(DiffIterator&& other) = default; + + DiffIterator& operator++() { + m_prev = std::move(m_curr); + m_curr = m_next; + + if (m_next != m_end) { + ++m_next; + } + + return *this; + } + + DiffIterator operator++(int) { + DiffIterator tmp(*this); + operator++(); + return tmp; + } + + bool operator==(const DiffIterator& rhs) const { + return m_curr == rhs.m_curr && m_end == rhs.m_end; + } + + bool operator!=(const DiffIterator& rhs) const { + return !(*this == rhs); + } + + reference operator*() const { + set_diff(); + return m_diff; + } + + pointer operator->() const { + set_diff(); + return &m_diff; + } + + }; // class DiffIterator + +} // namespace osmium + +#endif // OSMIUM_DIFF_ITERATOR_HPP diff --git a/ThirdParty/osmium/diff_visitor.hpp b/ThirdParty/osmium/diff_visitor.hpp new file mode 100644 index 000000000..a40df7df6 --- /dev/null +++ b/ThirdParty/osmium/diff_visitor.hpp @@ -0,0 +1,104 @@ +#ifndef OSMIUM_DIFF_VISITOR_HPP +#define OSMIUM_DIFF_VISITOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include + +namespace osmium { + + namespace detail { + + template + inline void apply_diff_iterator_recurse(const osmium::DiffObject& diff, THandler& handler) { + switch (diff.type()) { + case osmium::item_type::node: + handler.node(static_cast(diff)); + break; + case osmium::item_type::way: + handler.way(static_cast(diff)); + break; + case osmium::item_type::relation: + handler.relation(static_cast(diff)); + break; + default: + throw osmium::unknown_type(); + } + } + + template + inline void apply_diff_iterator_recurse(const osmium::DiffObject& diff, THandler& handler, TRest&... more) { + apply_diff_iterator_recurse(diff, handler); + apply_diff_iterator_recurse(diff, more...); + } + + } // namespace detail + + template + inline void apply_diff(TIterator it, TIterator end, THandlers&... handlers) { + typedef osmium::DiffIterator diff_iterator; + + diff_iterator dit(it, end); + diff_iterator dend(end, end); + + for (; dit != dend; ++dit) { + detail::apply_diff_iterator_recurse(*dit, handlers...); + } + } + + class OSMObject; + + template + inline void apply_diff(TSource& source, THandlers&... handlers) { + apply_diff(osmium::io::InputIterator {source}, + osmium::io::InputIterator {}, + handlers...); + } + + template + inline void apply_diff(osmium::memory::Buffer& buffer, THandlers&... handlers) { + apply_diff(buffer.begin(), buffer.end(), handlers...); + } + + template + inline void apply_diff(const osmium::memory::Buffer& buffer, THandlers&... handlers) { + apply_diff(buffer.cbegin(), buffer.cend(), handlers...); + } + +} // namespace osmium + +#endif // OSMIUM_DIFF_VISITOR_HPP diff --git a/ThirdParty/osmium/dynamic_handler.hpp b/ThirdParty/osmium/dynamic_handler.hpp new file mode 100644 index 000000000..115c09d3d --- /dev/null +++ b/ThirdParty/osmium/dynamic_handler.hpp @@ -0,0 +1,195 @@ +#ifndef OSMIUM_DYNAMIC_HANDLER_HPP +#define OSMIUM_DYNAMIC_HANDLER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include + +namespace osmium { + + class Node; + class Way; + class Relation; + class Area; + class Changeset; + + namespace handler { + + namespace detail { + + class HandlerWrapperBase { + + public: + + virtual ~HandlerWrapperBase() { + } + + virtual void node(const osmium::Node&) { + } + + virtual void way(const osmium::Way&) { + } + + virtual void relation(const osmium::Relation&) { + } + + virtual void area(const osmium::Area&) { + } + + virtual void changeset(const osmium::Changeset&) { + } + + virtual void flush() { + } + + }; // class HandlerWrapperBase + + + // The following uses trick from + // http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence + // to either call handler style functions or visitor style operator(). + +#define OSMIUM_DYNAMIC_HANDLER_DISPATCH(_name_, _type_) \ +template \ +auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, int) -> decltype(handler._name_(object), void()) { \ + handler._name_(object); \ +} \ +template \ +auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, long) -> decltype(handler(object), void()) { \ + handler(object); \ +} + + OSMIUM_DYNAMIC_HANDLER_DISPATCH(node, Node) + OSMIUM_DYNAMIC_HANDLER_DISPATCH(way, Way) + OSMIUM_DYNAMIC_HANDLER_DISPATCH(relation, Relation) + OSMIUM_DYNAMIC_HANDLER_DISPATCH(changeset, Changeset) + OSMIUM_DYNAMIC_HANDLER_DISPATCH(area, Area) + + template + auto flush_dispatch(THandler& handler, int) -> decltype(handler.flush(), void()) { + handler.flush(); + } + + template + void flush_dispatch(THandler&, long) {} + + template + class HandlerWrapper : public HandlerWrapperBase { + + THandler m_handler; + + public: + + template + HandlerWrapper(TArgs&&... args) : + m_handler(std::forward(args)...) { + } + + void node(const osmium::Node& node) override final { + node_dispatch(m_handler, node, 0); + } + + void way(const osmium::Way& way) override final { + way_dispatch(m_handler, way, 0); + } + + void relation(const osmium::Relation& relation) override final { + relation_dispatch(m_handler, relation, 0); + } + + void area(const osmium::Area& area) override final { + area_dispatch(m_handler, area, 0); + } + + void changeset(const osmium::Changeset& changeset) override final { + changeset_dispatch(m_handler, changeset, 0); + } + + void flush() override final { + flush_dispatch(m_handler, 0); + } + + }; // HandlerWrapper + + } // namespace detail + + class DynamicHandler : public osmium::handler::Handler { + + typedef std::unique_ptr impl_ptr; + impl_ptr m_impl; + + public: + + DynamicHandler() : + m_impl(impl_ptr(new osmium::handler::detail::HandlerWrapperBase)) { + } + + template + void set(TArgs&&... args) { + m_impl = impl_ptr(new osmium::handler::detail::HandlerWrapper(std::forward(args)...)); + } + + void node(const osmium::Node& node) { + m_impl->node(node); + } + + void way(const osmium::Way& way) { + m_impl->way(way); + } + + void relation(const osmium::Relation& relation) { + m_impl->relation(relation); + } + + void area(const osmium::Area& area) { + m_impl->area(area); + } + + void changeset(const osmium::Changeset& changeset) { + m_impl->changeset(changeset); + } + + void flush() { + m_impl->flush(); + } + + }; // DynamicHandler + + } // namspace handler + +} // namespace osmium + +#endif // OSMIUM_DYNAMIC_HANDLER_HPP diff --git a/ThirdParty/osmium/geom/coordinates.hpp b/ThirdParty/osmium/geom/coordinates.hpp new file mode 100644 index 000000000..694143c22 --- /dev/null +++ b/ThirdParty/osmium/geom/coordinates.hpp @@ -0,0 +1,106 @@ +#ifndef OSMIUM_GEOM_COORDINATES_HPP +#define OSMIUM_GEOM_COORDINATES_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include + +namespace osmium { + + namespace geom { + + namespace detail { + + /** + * Append double to string, removing superfluous '0' characters at + * the end. The decimal dot will also be removed if necessary. + */ + inline void double2string(std::string& s, double value) { + s += std::to_string(value); + + size_t len = s.size()-1; + while (s[len] == '0') --len; + if (s[len] == '.') --len; + + s.resize(len+1); + } + + } // namespace detail + + struct Coordinates { + + double x; + double y; + + explicit Coordinates(double cx, double cy) : x(cx), y(cy) { + } + + Coordinates(const osmium::Location& location) : x(location.lon()), y(location.lat()) { + } + + void append_to_string(std::string& s, const char infix) const { + osmium::geom::detail::double2string(s, x); + s += infix; + osmium::geom::detail::double2string(s, y); + } + + void append_to_string(std::string& s, const char prefix, const char infix, const char suffix) const { + s += prefix; + append_to_string(s, infix); + s += suffix; + } + + }; // struct coordinates + + inline bool operator==(const Coordinates& lhs, const Coordinates& rhs) { + return lhs.x == rhs.x && lhs.y == rhs.y; + } + + inline bool operator!=(const Coordinates& lhs, const Coordinates& rhs) { + return ! operator==(lhs, rhs); + } + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const Coordinates& c) { + return out << '(' << c.x << ',' << c.y << ')'; + } + + } // namespace geom + +} // namespace osmium + +#endif // OSMIUM_GEOM_COORDINATES_HPP diff --git a/ThirdParty/osmium/geom/factory.hpp b/ThirdParty/osmium/geom/factory.hpp new file mode 100644 index 000000000..1be404848 --- /dev/null +++ b/ThirdParty/osmium/geom/factory.hpp @@ -0,0 +1,282 @@ +#ifndef OSMIUM_GEOM_FACTORY_HPP +#define OSMIUM_GEOM_FACTORY_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + struct geometry_error : public std::runtime_error { + + geometry_error(const std::string& what) : + std::runtime_error(what) { + } + + geometry_error(const char* what) : + std::runtime_error(what) { + } + + }; // struct geometry_error + + /** + * @brief Everything related to geometry handling. + */ + namespace geom { + + /** + * Which nodes of a way to use for a linestring. + */ + enum class use_nodes : bool { + unique = true, ///< Remove consecutive nodes with same location. + all = false ///< Use all nodes. + }; + + /** + * Which direction the linestring created from a way + * should have. + */ + enum class direction : bool { + backward = true, ///< Linestring has reverse direction. + forward = false ///< Linestring has same direction as way. + }; + + /** + * This pseudo projection just returns its WGS84 input unchanged. + * Used as a template parameter if a real projection is not needed. + */ + class IdentityProjection { + + public: + + Coordinates operator()(osmium::Location location) const { + return Coordinates{location.lon(), location.lat()}; + } + + int epsg() const { + return 4326; + } + + std::string proj_string() const { + return "+proj=longlat +datum=WGS84 +no_defs"; + } + + }; // class IdentityProjection + + /** + * Geometry factory. + */ + template + class GeometryFactory { + + /** + * Add all points of an outer or inner ring to a multipolygon. + */ + void add_points(const osmium::OuterRing& nodes) { + osmium::Location last_location; + for (const osmium::NodeRef& node_ref : nodes) { + if (last_location != node_ref.location()) { + last_location = node_ref.location(); + m_impl.multipolygon_add_location(m_projection(last_location)); + } + } + } + + TProjection m_projection; + TGeomImpl m_impl; + + public: + + /** + * Constructor for default initialized projection. + */ + template + GeometryFactory(TArgs&&... args) : + m_projection(), + m_impl(std::forward(args)...) { + } + + /** + * Constructor for explicitly initialized projection. Note that the + * projection is moved into the GeometryFactory. + */ + template + GeometryFactory(TProjection&& projection, TArgs&&... args) : + m_projection(std::move(projection)), + m_impl(std::forward(args)...) { + } + + typedef typename TGeomImpl::point_type point_type; + typedef typename TGeomImpl::linestring_type linestring_type; + typedef typename TGeomImpl::polygon_type polygon_type; + typedef typename TGeomImpl::multipolygon_type multipolygon_type; + typedef typename TGeomImpl::ring_type ring_type; + + int epsg() const { + return m_projection.epsg(); + } + + std::string proj_string() const { + return m_projection.proj_string(); + } + + /* Point */ + + point_type create_point(const osmium::Location location) const { + return m_impl.make_point(m_projection(location)); + } + + point_type create_point(const osmium::Node& node) { + return create_point(node.location()); + } + + point_type create_point(const osmium::NodeRef& node_ref) { + return create_point(node_ref.location()); + } + + /* LineString */ + + template + size_t fill_linestring(TIter it, TIter end) { + size_t num_points = 0; + for (; it != end; ++it, ++num_points) { + m_impl.linestring_add_location(m_projection(it->location())); + } + return num_points; + } + + template + size_t fill_linestring_unique(TIter it, TIter end) { + size_t num_points = 0; + osmium::Location last_location; + for (; it != end; ++it) { + if (last_location != it->location()) { + last_location = it->location(); + m_impl.linestring_add_location(m_projection(last_location)); + ++num_points; + } + } + return num_points; + } + + linestring_type create_linestring(const osmium::WayNodeList& wnl, use_nodes un=use_nodes::unique, direction dir=direction::forward) { + m_impl.linestring_start(); + size_t num_points = 0; + + if (un == use_nodes::unique) { + osmium::Location last_location; + switch (dir) { + case direction::forward: + num_points = fill_linestring_unique(wnl.cbegin(), wnl.cend()); + break; + case direction::backward: + num_points = fill_linestring_unique(wnl.crbegin(), wnl.crend()); + break; + } + } else { + switch (dir) { + case direction::forward: + num_points = fill_linestring(wnl.cbegin(), wnl.cend()); + break; + case direction::backward: + num_points = fill_linestring(wnl.crbegin(), wnl.crend()); + break; + } + } + + if (num_points < 2) { + throw geometry_error("not enough points for linestring"); + } + + return m_impl.linestring_finish(num_points); + } + + linestring_type create_linestring(const osmium::Way& way, use_nodes un=use_nodes::unique, direction dir=direction::forward) { + return create_linestring(way.nodes(), un, dir); + } + + /* MultiPolygon */ + + multipolygon_type create_multipolygon(const osmium::Area& area) { + size_t num_polygons = 0; + size_t num_rings = 0; + m_impl.multipolygon_start(); + + for (auto it = area.cbegin(); it != area.cend(); ++it) { + const osmium::OuterRing& ring = static_cast(*it); + if (it->type() == osmium::item_type::outer_ring) { + if (num_polygons > 0) { + m_impl.multipolygon_polygon_finish(); + } + m_impl.multipolygon_polygon_start(); + m_impl.multipolygon_outer_ring_start(); + add_points(ring); + m_impl.multipolygon_outer_ring_finish(); + ++num_rings; + ++num_polygons; + } else if (it->type() == osmium::item_type::inner_ring) { + m_impl.multipolygon_inner_ring_start(); + add_points(ring); + m_impl.multipolygon_inner_ring_finish(); + ++num_rings; + } + } + + // if there are no rings, this area is invalid + if (num_rings == 0) { + throw geometry_error("invalid area"); + } + + m_impl.multipolygon_polygon_finish(); + return m_impl.multipolygon_finish(); + } + + }; // class GeometryFactory + + } // namespace geom + +} // namespace osmium + +#endif // OSMIUM_GEOM_FACTORY_HPP diff --git a/ThirdParty/osmium/geom/geojson.hpp b/ThirdParty/osmium/geom/geojson.hpp new file mode 100644 index 000000000..89efc3831 --- /dev/null +++ b/ThirdParty/osmium/geom/geojson.hpp @@ -0,0 +1,149 @@ +#ifndef OSMIUM_GEOM_GEOJSON_HPP +#define OSMIUM_GEOM_GEOJSON_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace geom { + + namespace detail { + + class GeoJSONFactoryImpl { + + std::string m_str; + + public: + + typedef std::string point_type; + typedef std::string linestring_type; + typedef std::string polygon_type; + typedef std::string multipolygon_type; + typedef std::string ring_type; + + GeoJSONFactoryImpl() = default; + + /* Point */ + + // { "type": "Point", "coordinates": [100.0, 0.0] } + point_type make_point(const osmium::geom::Coordinates& xy) const { + std::string str {"{\"type\":\"Point\",\"coordinates\":"}; + xy.append_to_string(str, '[', ',', ']'); + str += "}"; + return str; + } + + /* LineString */ + + // { "type": "LineString", "coordinates": [ [100.0, 0.0], [101.0, 1.0] ] } + void linestring_start() { + m_str = "{\"type\":\"LineString\",\"coordinates\":["; + } + + void linestring_add_location(const osmium::geom::Coordinates& xy) { + xy.append_to_string(m_str, '[', ',', ']'); + m_str += ','; + } + + linestring_type linestring_finish(size_t /* num_points */) { + assert(!m_str.empty()); + std::string str; + std::swap(str, m_str); + str.back() = ']'; + str += "}"; + return str; + } + + /* MultiPolygon */ + + void multipolygon_start() { + m_str = "{\"type\":\"MultiPolygon\",\"coordinates\":["; + } + + void multipolygon_polygon_start() { + m_str += '['; + } + + void multipolygon_polygon_finish() { + m_str += "],"; + } + + void multipolygon_outer_ring_start() { + m_str += '['; + } + + void multipolygon_outer_ring_finish() { + assert(!m_str.empty()); + m_str.back() = ']'; + } + + void multipolygon_inner_ring_start() { + m_str += ",["; + } + + void multipolygon_inner_ring_finish() { + assert(!m_str.empty()); + m_str.back() = ']'; + } + + void multipolygon_add_location(const osmium::geom::Coordinates& xy) { + xy.append_to_string(m_str, '[', ',', ']'); + m_str += ','; + } + + multipolygon_type multipolygon_finish() { + assert(!m_str.empty()); + m_str.back() = ']'; + m_str += "}"; + return std::move(m_str); + } + + }; // class GeoJSONFactoryImpl + + } // namespace detail + + template + using GeoJSONFactory = GeometryFactory; + + } // namespace geom + +} // namespace osmium + +#endif // OSMIUM_GEOM_GEOJSON_HPP diff --git a/ThirdParty/osmium/geom/geos.hpp b/ThirdParty/osmium/geom/geos.hpp new file mode 100644 index 000000000..877520b2c --- /dev/null +++ b/ThirdParty/osmium/geom/geos.hpp @@ -0,0 +1,224 @@ +#ifndef OSMIUM_GEOM_GEOS_HPP +#define OSMIUM_GEOM_GEOS_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#define OSMIUM_COMPILE_WITH_CFLAGS_GEOS `geos-config --cflags` +#define OSMIUM_LINK_WITH_LIBS_GEOS `geos-config --libs` + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// MSVC doesn't support throw_with_nested yet +#ifdef _MSC_VER +# define THROW throw +#else +# define THROW std::throw_with_nested +#endif + +namespace osmium { + + struct geos_geometry_error : public geometry_error { + + geos_geometry_error() : + geometry_error("geometry creation failed in GEOS library, see nested exception for details") { + } + + }; // struct geos_geometry_error + + namespace geom { + + namespace detail { + + class GEOSFactoryImpl { + + geos::geom::PrecisionModel m_precision_model; + geos::geom::GeometryFactory m_geos_factory; + + std::unique_ptr m_coordinate_sequence; + std::vector> m_rings; + std::vector> m_polygons; + + public: + + typedef std::unique_ptr point_type; + typedef std::unique_ptr linestring_type; + typedef std::unique_ptr polygon_type; + typedef std::unique_ptr multipolygon_type; + typedef std::unique_ptr ring_type; + + explicit GEOSFactoryImpl(int srid = -1) : + m_precision_model(), + m_geos_factory(&m_precision_model, srid) { + } + + /* Point */ + + point_type make_point(const osmium::geom::Coordinates& xy) const { + try { + return point_type(m_geos_factory.createPoint(geos::geom::Coordinate(xy.x, xy.y))); + } catch (geos::util::GEOSException&) { + THROW(osmium::geos_geometry_error()); + } + } + + /* LineString */ + + void linestring_start() { + try { + m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast(0), 2)); + } catch (geos::util::GEOSException&) { + THROW(osmium::geos_geometry_error()); + } + } + + void linestring_add_location(const osmium::geom::Coordinates& xy) { + try { + m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y)); + } catch (geos::util::GEOSException&) { + THROW(osmium::geos_geometry_error()); + } + } + + linestring_type linestring_finish(size_t /* num_points */) { + try { + return linestring_type(m_geos_factory.createLineString(m_coordinate_sequence.release())); + } catch (geos::util::GEOSException&) { + THROW(osmium::geos_geometry_error()); + } + } + + /* MultiPolygon */ + + void multipolygon_start() { + m_polygons.clear(); + } + + void multipolygon_polygon_start() { + m_rings.clear(); + } + + void multipolygon_polygon_finish() { + try { + assert(!m_rings.empty()); + auto inner_rings = new std::vector; + std::transform(std::next(m_rings.begin(), 1), m_rings.end(), std::back_inserter(*inner_rings), [](std::unique_ptr& r) { + return r.release(); + }); + m_polygons.emplace_back(m_geos_factory.createPolygon(m_rings[0].release(), inner_rings)); + m_rings.clear(); + } catch (geos::util::GEOSException&) { + THROW(osmium::geos_geometry_error()); + } + } + + void multipolygon_outer_ring_start() { + try { + m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast(0), 2)); + } catch (geos::util::GEOSException&) { + THROW(osmium::geos_geometry_error()); + } + } + + void multipolygon_outer_ring_finish() { + try { + m_rings.emplace_back(m_geos_factory.createLinearRing(m_coordinate_sequence.release())); + } catch (geos::util::GEOSException&) { + THROW(osmium::geos_geometry_error()); + } + } + + void multipolygon_inner_ring_start() { + try { + m_coordinate_sequence.reset(m_geos_factory.getCoordinateSequenceFactory()->create(static_cast(0), 2)); + } catch (geos::util::GEOSException&) { + THROW(osmium::geos_geometry_error()); + } + } + + void multipolygon_inner_ring_finish() { + try { + m_rings.emplace_back(m_geos_factory.createLinearRing(m_coordinate_sequence.release())); + } catch (geos::util::GEOSException&) { + THROW(osmium::geos_geometry_error()); + } + } + + void multipolygon_add_location(const osmium::geom::Coordinates& xy) { + try { + m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y)); + } catch (geos::util::GEOSException&) { + THROW(osmium::geos_geometry_error()); + } + } + + multipolygon_type multipolygon_finish() { + try { + auto polygons = new std::vector; + std::transform(m_polygons.begin(), m_polygons.end(), std::back_inserter(*polygons), [](std::unique_ptr& p) { + return p.release(); + }); + m_polygons.clear(); + return multipolygon_type(m_geos_factory.createMultiPolygon(polygons)); + } catch (geos::util::GEOSException&) { + THROW(osmium::geos_geometry_error()); + } + } + + }; // class GEOSFactoryImpl + + } // namespace detail + + template + using GEOSFactory = GeometryFactory; + + } // namespace geom + +} // namespace osmium + +#undef THROW + +#endif // OSMIUM_GEOM_GEOS_HPP diff --git a/ThirdParty/osmium/geom/haversine.hpp b/ThirdParty/osmium/geom/haversine.hpp new file mode 100644 index 000000000..5ce09b58d --- /dev/null +++ b/ThirdParty/osmium/geom/haversine.hpp @@ -0,0 +1,96 @@ +#ifndef OSMIUM_GEOM_HAVERSINE_HPP +#define OSMIUM_GEOM_HAVERSINE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace geom { + + /** + * @brief Functions to calculate arc distance on Earth using the haversine formula. + * + * See http://en.wikipedia.org/wiki/Haversine_formula + * + * Implementation derived from + * http://blog.julien.cayzac.name/2008/10/arc-and-distance-between-two-points-on.html + */ + namespace haversine { + + /// @brief Earth's quadratic mean radius for WGS84 + constexpr double EARTH_RADIUS_IN_METERS = 6372797.560856; + + /** + * Calculate distance in meters between two sets of coordinates. + */ + inline double distance(const osmium::geom::Coordinates& c1, const osmium::geom::Coordinates& c2) { + double lonh = sin(deg_to_rad(c1.x - c2.x) * 0.5); + lonh *= lonh; + double lath = sin(deg_to_rad(c1.y - c2.y) * 0.5); + lath *= lath; + const double tmp = cos(deg_to_rad(c1.y)) * cos(deg_to_rad(c2.y)); + return 2.0 * EARTH_RADIUS_IN_METERS * asin(sqrt(lath + tmp*lonh)); + } + + /** + * Calculate length of way. + */ + inline double distance(const osmium::WayNodeList& wnl) { + double sum_length=0; + + for (auto it = wnl.begin(); it != wnl.end(); ++it) { + if (std::next(it) != wnl.end()) { + sum_length += distance(it->location(), std::next(it)->location()); + } + } + + return sum_length; + } + + } // namespace haversine + + } // namespace geom + +} // namespace osmium + +#endif // OSMIUM_GEOM_HAVERSINE_HPP diff --git a/ThirdParty/osmium/geom/mercator_projection.hpp b/ThirdParty/osmium/geom/mercator_projection.hpp new file mode 100644 index 000000000..df0d47d8a --- /dev/null +++ b/ThirdParty/osmium/geom/mercator_projection.hpp @@ -0,0 +1,109 @@ +#ifndef OSMIUM_GEOM_MERCATOR_PROJECTION_HPP +#define OSMIUM_GEOM_MERCATOR_PROJECTION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include +#include +#include + +namespace osmium { + + namespace geom { + + namespace detail { + + constexpr double EARTH_RADIUS_FOR_EPSG3857 = 6378137.0; + + constexpr inline double lon_to_x(double lon) { + return EARTH_RADIUS_FOR_EPSG3857 * deg_to_rad(lon); + } + + inline double lat_to_y(double lat) { // not constexpr because math functions aren't + return EARTH_RADIUS_FOR_EPSG3857 * std::log(std::tan(osmium::geom::PI/4 + deg_to_rad(lat)/2)); + } + + constexpr inline double x_to_lon(double x) { + return rad_to_deg(x) / EARTH_RADIUS_FOR_EPSG3857; + } + + inline double y_to_lat(double y) { // not constexpr because math functions aren't + return rad_to_deg(2 * std::atan(std::exp(y / EARTH_RADIUS_FOR_EPSG3857)) - osmium::geom::PI/2); + } + + } // namespace detail + + /** + * The maximum latitude that can be projected with the Web Mercator + * (EPSG:3857) projection. + */ + constexpr double MERCATOR_MAX_LAT = 85.0511288; + + inline Coordinates lonlat_to_mercator(const Coordinates& c) { + return Coordinates(detail::lon_to_x(c.x), detail::lat_to_y(c.y)); + } + + inline Coordinates mercator_to_lonlat(const Coordinates& c) { + return Coordinates(detail::x_to_lon(c.x), detail::y_to_lat(c.y)); + } + + /** + * Functor that does projection from WGS84 (EPSG:4326) to "Web + * Mercator" (EPSG:3857) + */ + class MercatorProjection { + + public: + + Coordinates operator()(osmium::Location location) const { + return Coordinates {detail::lon_to_x(location.lon()), detail::lat_to_y(location.lat())}; + } + + int epsg() const { + return 3857; + } + + std::string proj_string() const { + return "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"; + } + + }; // class MercatorProjection + + } // namespace geom + +} // namespace osmium + +#endif // OSMIUM_GEOM_MERCATOR_PROJECTION_HPP diff --git a/ThirdParty/osmium/geom/ogr.hpp b/ThirdParty/osmium/geom/ogr.hpp new file mode 100644 index 000000000..c730de85c --- /dev/null +++ b/ThirdParty/osmium/geom/ogr.hpp @@ -0,0 +1,157 @@ +#ifndef OSMIUM_GEOM_OGR_HPP +#define OSMIUM_GEOM_OGR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#define OSMIUM_COMPILE_WITH_CFLAGS_OGR `gdal-config --cflags` +#define OSMIUM_LINK_WITH_LIBS_OGR `gdal-config --libs` + +#include +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdocumentation-unknown-command" +# include +#pragma GCC diagnostic pop + +#include +#include + +namespace osmium { + + namespace geom { + + namespace detail { + + class OGRFactoryImpl { + + public: + + typedef std::unique_ptr point_type; + typedef std::unique_ptr linestring_type; + typedef std::unique_ptr polygon_type; + typedef std::unique_ptr multipolygon_type; + typedef std::unique_ptr ring_type; + + private: + + linestring_type m_linestring; + multipolygon_type m_multipolygon; + polygon_type m_polygon; + ring_type m_ring; + + public: + + OGRFactoryImpl() = default; + + /* Point */ + + point_type make_point(const osmium::geom::Coordinates& xy) const { + return point_type(new OGRPoint(xy.x, xy.y)); + } + + /* LineString */ + + void linestring_start() { + m_linestring = std::unique_ptr(new OGRLineString()); + } + + void linestring_add_location(const osmium::geom::Coordinates& xy) { + assert(!!m_linestring); + m_linestring->addPoint(xy.x, xy.y); + } + + linestring_type linestring_finish(size_t /* num_points */) { + return std::move(m_linestring); + } + + /* MultiPolygon */ + + void multipolygon_start() { + m_multipolygon.reset(new OGRMultiPolygon()); + } + + void multipolygon_polygon_start() { + m_polygon.reset(new OGRPolygon()); + } + + void multipolygon_polygon_finish() { + assert(!!m_multipolygon); + assert(!!m_polygon); + m_multipolygon->addGeometryDirectly(m_polygon.release()); + } + + void multipolygon_outer_ring_start() { + m_ring.reset(new OGRLinearRing()); + } + + void multipolygon_outer_ring_finish() { + assert(!!m_polygon); + assert(!!m_ring); + m_polygon->addRingDirectly(m_ring.release()); + } + + void multipolygon_inner_ring_start() { + m_ring.reset(new OGRLinearRing()); + } + + void multipolygon_inner_ring_finish() { + assert(!!m_polygon); + assert(!!m_ring); + m_polygon->addRingDirectly(m_ring.release()); + } + + void multipolygon_add_location(const osmium::geom::Coordinates& xy) { + assert(!!m_polygon); + assert(!!m_ring); + m_ring->addPoint(xy.x, xy.y); + } + + multipolygon_type multipolygon_finish() { + assert(!!m_multipolygon); + return std::move(m_multipolygon); + } + + }; // class OGRFactoryImpl + + } // namespace detail + + template + using OGRFactory = GeometryFactory; + + } // namespace geom + +} // namespace osmium + +#endif // OSMIUM_GEOM_OGR_HPP diff --git a/ThirdParty/osmium/geom/projection.hpp b/ThirdParty/osmium/geom/projection.hpp new file mode 100644 index 000000000..2f9849fe7 --- /dev/null +++ b/ThirdParty/osmium/geom/projection.hpp @@ -0,0 +1,159 @@ +#ifndef OSMIUM_GEOM_PROJECTION_HPP +#define OSMIUM_GEOM_PROJECTION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#define OSMIUM_LINK_WITH_LIBS_PROJ -lproj + +#include +#include + +#include + +#include +#include +#include + +namespace osmium { + + namespace geom { + + /** + * C++ wrapper for a Coordinate Reference System of the proj library. + */ + class CRS { + + struct ProjCRSDeleter { + void operator()(void* crs) { + pj_free(crs); + } + }; + + std::unique_ptr m_crs; + + projPJ get() const { + return m_crs.get(); + } + + public: + + CRS(const std::string& crs) : + m_crs(pj_init_plus(crs.c_str()), ProjCRSDeleter()) { + if (!m_crs) { + throw osmium::projection_error(std::string("creation of CRS failed: ") + pj_strerrno(*pj_get_errno_ref())); + } + } + + CRS(int epsg) : + CRS(std::string("+init=epsg:") + std::to_string(epsg)) { + } + + bool is_latlong() const { + return pj_is_latlong(m_crs.get()); + } + + bool is_geocent() const { + return pj_is_geocent(m_crs.get()); + } + + /** + * Transform coordinates from one CRS into another. Wraps the same function + * of the proj library. + * + * Coordinates have to be in radians and are produced in radians. + * + * @throws osmmium::projection_error if the projection fails + */ + friend Coordinates transform(const CRS& src, const CRS& dest, Coordinates c) { + int result = pj_transform(src.get(), dest.get(), 1, 1, &c.x, &c.y, nullptr); + if (result != 0) { + throw osmium::projection_error(std::string("projection failed: ") + pj_strerrno(result)); + } + return c; + } + + }; // class CRS + + /** + * Functor that does projection from WGS84 (EPSG:4326) in to the given + * CRS. + */ + class Projection { + + int m_epsg; + std::string m_proj_string; + CRS m_crs_wgs84 {4326}; + CRS m_crs_user; + + public: + + Projection(const std::string& proj_string) : + m_epsg(-1), + m_proj_string(proj_string), + m_crs_user(proj_string) { + } + + Projection(int epsg) : + m_epsg(epsg), + m_proj_string(std::string("+init=epsg:") + std::to_string(epsg)), + m_crs_user(epsg) { + } + + Coordinates operator()(osmium::Location location) const { + if (m_epsg == 4326) { + return Coordinates(location.lon(), location.lat()); + } else { + Coordinates c = transform(m_crs_wgs84, m_crs_user, Coordinates(deg_to_rad(location.lon()), deg_to_rad(location.lat()))); + if (m_crs_user.is_latlong()) { + c.x = rad_to_deg(c.x); + c.y = rad_to_deg(c.y); + } + return c; + } + } + + int epsg() const { + return m_epsg; + } + + std::string proj_string() const { + return m_proj_string; + } + + }; // class Projection + + } // namespace geom + +} // namespace osmium + +#endif // OSMIUM_GEOM_PROJECTION_HPP diff --git a/ThirdParty/osmium/geom/relations.hpp b/ThirdParty/osmium/geom/relations.hpp new file mode 100644 index 000000000..156837b6d --- /dev/null +++ b/ThirdParty/osmium/geom/relations.hpp @@ -0,0 +1,57 @@ +#ifndef OSMIUM_GEOM_RELATIONS_HPP +#define OSMIUM_GEOM_RELATIONS_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +namespace osmium { + + namespace geom { + + /** + * Check whether one geometry contains another. + */ + inline bool contains(const osmium::Box& a, const osmium::Box& b) { + return ((a.bottom_left().x() >= b.bottom_left().x()) && + (a.top_right().x() <= b.top_right().x()) && + (a.bottom_left().y() >= b.bottom_left().y()) && + (a.top_right().y() <= b.top_right().y())); + } + + } // namespace geom + +} // namespace osmium + +#endif // OSMIUM_GEOM_RELATIONS_HPP diff --git a/ThirdParty/osmium/geom/util.hpp b/ThirdParty/osmium/geom/util.hpp new file mode 100644 index 000000000..25ea74626 --- /dev/null +++ b/ThirdParty/osmium/geom/util.hpp @@ -0,0 +1,71 @@ +#ifndef OSMIUM_GEOM_UTIL_HPP +#define OSMIUM_GEOM_UTIL_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +namespace osmium { + + struct projection_error : public std::runtime_error { + + projection_error(const std::string& what) : + std::runtime_error(what) { + } + + projection_error(const char* what) : + std::runtime_error(what) { + } + + }; // struct projection_error + + namespace geom { + + constexpr double PI = 3.14159265358979323846; + + /// Convert angle from degrees to radians. + inline constexpr double deg_to_rad(double degree) { + return degree * (PI / 180.0); + } + + /// Convert angle from radians to degrees. + inline constexpr double rad_to_deg(double radians) { + return radians * (180.0 / PI); + } + + } // namespace geom + +} // namespace osmium + +#endif // OSMIUM_GEOM_UTIL_HPP diff --git a/ThirdParty/osmium/geom/wkb.hpp b/ThirdParty/osmium/geom/wkb.hpp new file mode 100644 index 000000000..ac4c47bc8 --- /dev/null +++ b/ThirdParty/osmium/geom/wkb.hpp @@ -0,0 +1,264 @@ +#ifndef OSMIUM_GEOM_WKB_HPP +#define OSMIUM_GEOM_WKB_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace geom { + + enum class wkb_type : bool { + wkb = false, + ewkb = true + }; + + enum class out_type : bool { + binary = false, + hex = true + }; + + namespace detail { + + template + inline void str_push(std::string& str, T data) { + size_t size = str.size(); + str.resize(size + sizeof(T)); + std::memcpy(const_cast(&str[size]), reinterpret_cast(&data), sizeof(T)); + } + + inline std::string convert_to_hex(std::string& str) { + static const char* lookup_hex = "0123456789ABCDEF"; + std::string out; + + for (char c : str) { + out += lookup_hex[(c >> 4) & 0xf]; + out += lookup_hex[c & 0xf]; + } + + return out; + } + + class WKBFactoryImpl { + + /// OSM data always uses SRID 4326 (WGS84). + static constexpr uint32_t srid = 4326; + + /** + * Type of WKB geometry. + * These definitions are from + * 99-049_OpenGIS_Simple_Features_Specification_For_SQL_Rev_1.1.pdf (for WKB) + * and http://trac.osgeo.org/postgis/browser/trunk/doc/ZMSgeoms.txt (for EWKB). + * They are used to encode geometries into the WKB format. + */ + enum wkbGeometryType : uint32_t { + wkbPoint = 1, + wkbLineString = 2, + wkbPolygon = 3, + wkbMultiPoint = 4, + wkbMultiLineString = 5, + wkbMultiPolygon = 6, + wkbGeometryCollection = 7, + + // SRID-presence flag (EWKB) + wkbSRID = 0x20000000 + }; + + /** + * Byte order marker in WKB geometry. + */ + enum class wkb_byte_order_type : uint8_t { + XDR = 0, // Big Endian + NDR = 1 // Little Endian + }; + + std::string m_data; + uint32_t m_points {0}; + wkb_type m_wkb_type; + out_type m_out_type; + + size_t m_linestring_size_offset = 0; + size_t m_polygons = 0; + size_t m_rings = 0; + size_t m_multipolygon_size_offset = 0; + size_t m_polygon_size_offset = 0; + size_t m_ring_size_offset = 0; + + size_t header(std::string& str, wkbGeometryType type, bool add_length) const { + str_push(str, wkb_byte_order_type::NDR); + if (m_wkb_type == wkb_type::ewkb) { + str_push(str, type | wkbSRID); + str_push(str, srid); + } else { + str_push(str, type); + } + size_t offset = str.size(); + if (add_length) { + str_push(str, static_cast(0)); + } + return offset; + } + + void set_size(const size_t offset, const uint32_t size) { + memcpy(&m_data[offset], &size, sizeof(uint32_t)); + } + + public: + + typedef std::string point_type; + typedef std::string linestring_type; + typedef std::string polygon_type; + typedef std::string multipolygon_type; + typedef std::string ring_type; + + explicit WKBFactoryImpl(wkb_type wtype=wkb_type::wkb, out_type otype=out_type::binary) : + m_wkb_type(wtype), + m_out_type(otype) { + } + + /* Point */ + + point_type make_point(const osmium::geom::Coordinates& xy) const { + std::string data; + header(data, wkbPoint, false); + str_push(data, xy.x); + str_push(data, xy.y); + + if (m_out_type == out_type::hex) { + return convert_to_hex(data); + } else { + return data; + } + } + + /* LineString */ + + void linestring_start() { + m_data.clear(); + m_linestring_size_offset = header(m_data, wkbLineString, true); + } + + void linestring_add_location(const osmium::geom::Coordinates& xy) { + str_push(m_data, xy.x); + str_push(m_data, xy.y); + } + + linestring_type linestring_finish(size_t num_points) { + set_size(m_linestring_size_offset, num_points); + std::string data; + std::swap(data, m_data); + + if (m_out_type == out_type::hex) { + return convert_to_hex(data); + } else { + return data; + } + } + + /* MultiPolygon */ + + void multipolygon_start() { + m_data.clear(); + m_polygons = 0; + m_multipolygon_size_offset = header(m_data, wkbMultiPolygon, true); + } + + void multipolygon_polygon_start() { + ++m_polygons; + m_rings = 0; + m_polygon_size_offset = header(m_data, wkbPolygon, true); + } + + void multipolygon_polygon_finish() { + set_size(m_polygon_size_offset, m_rings); + } + + void multipolygon_outer_ring_start() { + ++m_rings; + m_points = 0; + m_ring_size_offset = m_data.size(); + str_push(m_data, static_cast(0)); + } + + void multipolygon_outer_ring_finish() { + set_size(m_ring_size_offset, m_points); + } + + void multipolygon_inner_ring_start() { + ++m_rings; + m_points = 0; + m_ring_size_offset = m_data.size(); + str_push(m_data, static_cast(0)); + } + + void multipolygon_inner_ring_finish() { + set_size(m_ring_size_offset, m_points); + } + + void multipolygon_add_location(const osmium::geom::Coordinates& xy) { + str_push(m_data, xy.x); + str_push(m_data, xy.y); + ++m_points; + } + + multipolygon_type multipolygon_finish() { + set_size(m_multipolygon_size_offset, m_polygons); + std::string data; + std::swap(data, m_data); + + if (m_out_type == out_type::hex) { + return convert_to_hex(data); + } else { + return data; + } + } + + }; // class WKBFactoryImpl + + } // namespace detail + + template + using WKBFactory = GeometryFactory; + + } // namespace geom + +} // namespace osmium + +#endif // OSMIUM_GEOM_WKB_HPP diff --git a/ThirdParty/osmium/geom/wkt.hpp b/ThirdParty/osmium/geom/wkt.hpp new file mode 100644 index 000000000..dd12ad34e --- /dev/null +++ b/ThirdParty/osmium/geom/wkt.hpp @@ -0,0 +1,142 @@ +#ifndef OSMIUM_GEOM_WKT_HPP +#define OSMIUM_GEOM_WKT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace geom { + + namespace detail { + + class WKTFactoryImpl { + + std::string m_str; + + public: + + typedef std::string point_type; + typedef std::string linestring_type; + typedef std::string polygon_type; + typedef std::string multipolygon_type; + typedef std::string ring_type; + + /* Point */ + + point_type make_point(const osmium::geom::Coordinates& xy) const { + std::string str {"POINT"}; + xy.append_to_string(str, '(', ' ', ')'); + return str; + } + + /* LineString */ + + void linestring_start() { + m_str = "LINESTRING("; + } + + void linestring_add_location(const osmium::geom::Coordinates& xy) { + xy.append_to_string(m_str, ' '); + m_str += ','; + } + + linestring_type linestring_finish(size_t /* num_points */) { + assert(!m_str.empty()); + std::string str; + std::swap(str, m_str); + str.back() = ')'; + return str; + } + + /* MultiPolygon */ + + void multipolygon_start() { + m_str = "MULTIPOLYGON("; + } + + void multipolygon_polygon_start() { + m_str += '('; + } + + void multipolygon_polygon_finish() { + m_str += "),"; + } + + void multipolygon_outer_ring_start() { + m_str += '('; + } + + void multipolygon_outer_ring_finish() { + assert(!m_str.empty()); + m_str.back() = ')'; + } + + void multipolygon_inner_ring_start() { + m_str += ",("; + } + + void multipolygon_inner_ring_finish() { + assert(!m_str.empty()); + m_str.back() = ')'; + } + + void multipolygon_add_location(const osmium::geom::Coordinates& xy) { + xy.append_to_string(m_str, ' '); + m_str += ','; + } + + multipolygon_type multipolygon_finish() { + assert(!m_str.empty()); + m_str.back() = ')'; + return std::move(m_str); + } + + }; // class WKTFactoryImpl + + } // namespace detail + + template + using WKTFactory = GeometryFactory; + + } // namespace geom + +} // namespace osmium + +#endif // OSMIUM_GEOM_WKT_HPP diff --git a/ThirdParty/osmium/handler.hpp b/ThirdParty/osmium/handler.hpp new file mode 100644 index 000000000..88bfbaccf --- /dev/null +++ b/ThirdParty/osmium/handler.hpp @@ -0,0 +1,101 @@ +#ifndef OSMIUM_HANDLER_HPP +#define OSMIUM_HANDLER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +namespace osmium { + + class OSMObject; + class Node; + class Way; + class Relation; + class Area; + class Changeset; + class TagList; + class WayNodeList; + class RelationMemberList; + class OuterRing; + class InnerRing; + + /** + * @brief Osmium handlers provide callbacks for OSM objects + */ + namespace handler { + + class Handler { + + public: + + void osm_object(const osmium::OSMObject&) const { + } + + void node(const osmium::Node&) const { + } + + void way(const osmium::Way&) const { + } + + void relation(const osmium::Relation&) const { + } + + void area(const osmium::Area&) const { + } + + void changeset(const osmium::Changeset&) const { + } + + void tag_list(const osmium::TagList&) const { + } + + void way_node_list(const osmium::WayNodeList&) const { + } + + void relation_member_list(const osmium::RelationMemberList&) const { + } + + void outer_ring(const osmium::OuterRing&) const { + } + + void inner_ring(const osmium::InnerRing&) const { + } + + void flush() const { + } + + }; // class Handler + + } // namspace handler + +} // namespace osmium + +#endif // OSMIUM_HANDLER_HPP diff --git a/ThirdParty/osmium/handler/chain.hpp b/ThirdParty/osmium/handler/chain.hpp new file mode 100644 index 000000000..a7bf10e9a --- /dev/null +++ b/ThirdParty/osmium/handler/chain.hpp @@ -0,0 +1,128 @@ +#ifndef OSMIUM_HANDLER_CHAIN_HPP +#define OSMIUM_HANDLER_CHAIN_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +#include + +#define OSMIUM_CHAIN_HANDLER_CALL(_func_, _type_) \ + template \ + struct call_ ## _func_ { \ + void operator()(THandlers& handlers, osmium::_type_& object) { \ + std::get(handlers)._func_(object); \ + call_ ## _func_()(handlers, object); \ + } \ + }; \ + template \ + struct call_ ## _func_ { \ + void operator()(THandlers&, osmium::_type_&) {} \ + }; + +namespace osmium { + + class Node; + class Way; + class Relation; + class Area; + class Changeset; + + namespace handler { + + /** + * This handler allows chaining of any number of handlers into a single + * handler. + */ + template + class ChainHandler : public osmium::handler::Handler { + + typedef std::tuple handlers_type; + handlers_type m_handlers; + + template + struct call_flush { + void operator()(THandlers& handlers) { + std::get(handlers).flush(); + call_flush()(handlers); + } + }; + + template + struct call_flush { + void operator()(THandlers&) {} + }; + + OSMIUM_CHAIN_HANDLER_CALL(node, Node) + OSMIUM_CHAIN_HANDLER_CALL(way, Way) + OSMIUM_CHAIN_HANDLER_CALL(relation, Relation) + OSMIUM_CHAIN_HANDLER_CALL(changeset, Changeset) + OSMIUM_CHAIN_HANDLER_CALL(area, Area) + + public: + + explicit ChainHandler(THandler&... handlers) : + m_handlers(handlers...) { + } + + void node(osmium::Node& node) { + call_node<0, sizeof...(THandler), handlers_type>()(m_handlers, node); + } + + void way(osmium::Way& way) { + call_way<0, sizeof...(THandler), handlers_type>()(m_handlers, way); + } + + void relation(osmium::Relation& relation) { + call_relation<0, sizeof...(THandler), handlers_type>()(m_handlers, relation); + } + + void changeset( osmium::Changeset& changeset) { + call_changeset<0, sizeof...(THandler), handlers_type>()(m_handlers, changeset); + } + + void area(osmium::Area& area) { + call_area<0, sizeof...(THandler), handlers_type>()(m_handlers, area); + } + + void flush() { + call_flush<0, sizeof...(THandler), handlers_type>()(m_handlers); + } + + }; // class ChainHandler + + } // namespace handler + +} // namespace osmium + +#endif // OSMIUM_HANDLER_CHAIN_HPP diff --git a/ThirdParty/osmium/handler/disk_store.hpp b/ThirdParty/osmium/handler/disk_store.hpp new file mode 100644 index 000000000..137670a18 --- /dev/null +++ b/ThirdParty/osmium/handler/disk_store.hpp @@ -0,0 +1,111 @@ +#ifndef OSMIUM_HANDLER_DISK_STORE_HPP +#define OSMIUM_HANDLER_DISK_STORE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace handler { + + /** + * + * Note: This handler will only work if either all object IDs are + * positive or all object IDs are negative. + */ + class DiskStore : public osmium::handler::Handler { + + typedef osmium::index::map::Map offset_index_type; + + size_t m_offset = 0; + int m_data_fd; + + offset_index_type& m_node_index; + offset_index_type& m_way_index; + offset_index_type& m_relation_index; + + public: + + explicit DiskStore(int data_fd, offset_index_type& node_index, offset_index_type& way_index, offset_index_type& relation_index) : + m_data_fd(data_fd), + m_node_index(node_index), + m_way_index(way_index), + m_relation_index(relation_index) { + } + + DiskStore(const DiskStore&) = delete; + DiskStore& operator=(const DiskStore&) = delete; + + ~DiskStore() noexcept = default; + + void node(const osmium::Node& node) { + m_node_index.set(node.positive_id(), m_offset); + m_offset += node.byte_size(); + } + + void way(const osmium::Way& way) { + m_way_index.set(way.positive_id(), m_offset); + m_offset += way.byte_size(); + } + + void relation(const osmium::Relation& relation) { + m_relation_index.set(relation.positive_id(), m_offset); + m_offset += relation.byte_size(); + } + + // XXX + void operator()(const osmium::memory::Buffer& buffer) { + osmium::io::detail::reliable_write(m_data_fd, buffer.data(), buffer.committed()); + + osmium::apply(buffer.begin(), buffer.end(), *this); + } + + }; // class DiskStore + + } // namespace handler + +} // namespace osmium + +#endif // OSMIUM_HANDLER_DISK_STORE_HPP diff --git a/ThirdParty/osmium/handler/dump.hpp b/ThirdParty/osmium/handler/dump.hpp new file mode 100644 index 000000000..63c66e39e --- /dev/null +++ b/ThirdParty/osmium/handler/dump.hpp @@ -0,0 +1,294 @@ +#ifndef OSMIUM_HANDLER_DUMP_HPP +#define OSMIUM_HANDLER_DUMP_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace handler { + + class Dump : public osmium::handler::Handler { + + std::ostream& m_out; + bool m_with_size; + std::string m_prefix; + + void print_title(const char* title, const osmium::memory::Item& item) { + m_out << m_prefix + << title + << ":"; + + if (m_with_size) { + m_out << " [" + << item.byte_size() + << "]"; + } + + m_out << "\n"; + } + + void print_meta(const osmium::OSMObject& object) { + m_out << m_prefix + << " id=" + << object.id() + << "\n"; + m_out << m_prefix + << " version=" + << object.version() + << "\n"; + m_out << m_prefix + << " uid=" + << object.uid() + << "\n"; + m_out << m_prefix + << " user=|" + << object.user() + << "|\n"; + m_out << m_prefix + << " changeset=" + << object.changeset() + << "\n"; + m_out << m_prefix + << " timestamp=" + << object.timestamp().to_iso() + << "\n"; + m_out << m_prefix + << " visible=" + << (object.visible() ? "yes" : "no") + << "\n"; + + Dump dump(m_out, m_with_size, m_prefix + " "); + osmium::apply(object.cbegin(), object.cend(), dump); + } + + void print_location(const osmium::Node& node) { + const osmium::Location& location = node.location(); + + if (location) { + m_out << m_prefix + << " lon=" + << std::fixed + << std::setprecision(7) + << location.lon_without_check() + << "\n"; + m_out << m_prefix + << " lat=" + << location.lat_without_check() + << "\n"; + } else { + m_out << m_prefix + << " lon=\n" + << m_prefix + << " lat=\n"; + } + } + + public: + + explicit Dump(std::ostream& out, bool with_size=true, const std::string& prefix="") : + m_out(out), + m_with_size(with_size), + m_prefix(prefix) { + } + + void tag_list(const osmium::TagList& tags) { + print_title("TAGS", tags); + for (const auto& tag : tags) { + m_out << m_prefix + << " k=|" + << tag.key() + << "| v=|" + << tag.value() + << "|" + << "\n"; + } + } + + void way_node_list(const osmium::WayNodeList& wnl) { + print_title("NODES", wnl); + for (const auto& node_ref : wnl) { + m_out << m_prefix + << " ref=" + << node_ref.ref(); + if (node_ref.location()) { + m_out << " pos=" + << node_ref.location(); + } + m_out << "\n"; + } + } + + void relation_member_list(const osmium::RelationMemberList& rml) { + print_title("MEMBERS", rml); + for (const auto& member : rml) { + m_out << m_prefix + << " type=" + << item_type_to_name(member.type()) + << " ref=" + << member.ref() + << " role=|" + << member.role() + << "|\n"; + if (member.full_member()) { + Dump dump(m_out, m_with_size, m_prefix + " | "); + osmium::apply_item(member.get_object(), dump); + } + } + } + + void outer_ring(const osmium::OuterRing& ring) { + print_title("OUTER RING", ring); + for (const auto& node_ref : ring) { + m_out << m_prefix + << " ref=" + << node_ref.ref(); + if (node_ref.location()) { + m_out << " pos=" + << node_ref.location(); + } + m_out << "\n"; + } + } + + void inner_ring(const osmium::InnerRing& ring) { + print_title("INNER RING", ring); + for (const auto& node_ref : ring) { + m_out << m_prefix + << " ref=" + << node_ref.ref(); + if (node_ref.location()) { + m_out << " pos=" + << node_ref.location(); + } + m_out << "\n"; + } + } + + void node(const osmium::Node& node) { + print_title("NODE", node); + print_meta(node); + print_location(node); + } + + void way(const osmium::Way& way) { + print_title("WAY", way); + print_meta(way); + } + + void relation(const osmium::Relation& relation) { + print_title("RELATION", relation); + print_meta(relation); + } + + void area(const osmium::Area& area) { + print_title("AREA", area); + print_meta(area); + } + + void changeset(const osmium::Changeset& changeset) { + print_title("CHANGESET", changeset); + m_out << m_prefix + << " id=" + << changeset.id() + << "\n"; + m_out << m_prefix + << " num_changes=" + << changeset.num_changes() + << "\n"; + m_out << m_prefix + << " uid=" + << changeset.uid() + << "\n"; + m_out << m_prefix + << " user=|" + << changeset.user() + << "|\n"; + m_out << m_prefix + << " created_at=" + << changeset.created_at().to_iso() + << "\n"; + m_out << m_prefix + << " closed_at=" + << changeset.closed_at().to_iso() + << "\n"; + m_out << m_prefix + << " bounds="; + + if (changeset.bounds()) { + m_out << '(' + << changeset.bounds().bottom_left().lon_without_check() + << ',' + << changeset.bounds().bottom_left().lat_without_check() + << ',' + << changeset.bounds().top_right().lon_without_check() + << ',' + << changeset.bounds().top_right().lat_without_check() + << ')'; + } else { + m_out << "(undefined)"; + } + + m_out << "\n"; + + Dump dump(m_out, m_with_size, m_prefix + " "); + osmium::apply(changeset.cbegin(), changeset.cend(), dump); + } + + }; // class Dump + + } // namespace handler + +} // namespace osmium + +#endif // OSMIUM_HANDLER_DUMP_HPP diff --git a/ThirdParty/osmium/handler/node_locations_for_ways.hpp b/ThirdParty/osmium/handler/node_locations_for_ways.hpp new file mode 100644 index 000000000..695eae010 --- /dev/null +++ b/ThirdParty/osmium/handler/node_locations_for_ways.hpp @@ -0,0 +1,148 @@ +#ifndef OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP +#define OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace handler { + + typedef osmium::index::map::Dummy dummy_type; + + /** + * Handler to retrieve locations from nodes and add them to ways. + * + * @tparam TStoragePosIDs Class that handles the actual storage of the node locations + * (for positive IDs). It must support the set(id, value) and + * get(id) methods. + * @tparam TStorageNegIDs Same but for negative IDs. + */ + template + class NodeLocationsForWays : public osmium::handler::Handler { + + /// Object that handles the actual storage of the node locations (with positive IDs). + TStoragePosIDs& m_storage_pos; + + /// Object that handles the actual storage of the node locations (with negative IDs). + TStorageNegIDs& m_storage_neg; + + bool m_ignore_errors {false}; + + bool m_must_sort {false}; + + // It is okay to have this static dummy instance, even when using several threads, + // because it is read-only. + static dummy_type& get_dummy() { + static dummy_type instance; + return instance; + } + + public: + + explicit NodeLocationsForWays(TStoragePosIDs& storage_pos, + TStorageNegIDs& storage_neg = get_dummy()) : + m_storage_pos(storage_pos), + m_storage_neg(storage_neg) { + } + + NodeLocationsForWays(const NodeLocationsForWays&) = delete; + NodeLocationsForWays& operator=(const NodeLocationsForWays&) = delete; + + ~NodeLocationsForWays() noexcept = default; + + void ignore_errors() { + m_ignore_errors = true; + } + + /** + * Store the location of the node in the storage. + */ + void node(const osmium::Node& node) { + m_must_sort = true; + const osmium::object_id_type id = node.id(); + if (id >= 0) { + m_storage_pos.set(id, node.location()); + } else { + m_storage_neg.set(-id, node.location()); + } + } + + /** + * Get location of node with given id. + */ + osmium::Location get_node_location(const osmium::object_id_type id) const { + return id >= 0 ? m_storage_pos.get(id) : m_storage_neg.get(-id); + } + + /** + * Retrieve locations of all nodes in the way from storage and add + * them to the way object. + */ + void way(osmium::Way& way) { + if (m_must_sort) { + m_storage_pos.sort(); + m_storage_neg.sort(); + m_must_sort = false; + } + bool error = false; + for (auto& node_ref : way.nodes()) { + try { + node_ref.location(get_node_location(node_ref.ref())); + if (!node_ref.location()) { + error = true; + } + } catch (osmium::not_found&) { + error = true; + } + } + if (error && !m_ignore_errors) { + throw osmium::not_found("not found"); + } + } + + }; // class NodeLocationsForWays + + } // namespace handler + +} // namespace osmium + +#endif // OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP diff --git a/ThirdParty/osmium/handler/object_relations.hpp b/ThirdParty/osmium/handler/object_relations.hpp new file mode 100644 index 000000000..5b5b01735 --- /dev/null +++ b/ThirdParty/osmium/handler/object_relations.hpp @@ -0,0 +1,106 @@ +#ifndef OSMIUM_HANDLER_OBJECT_RELATIONS_HPP +#define OSMIUM_HANDLER_OBJECT_RELATIONS_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace handler { + + /** + * + * Note: This handler will only work if either all object IDs are + * positive or all object IDs are negative. + */ + class ObjectRelations : public osmium::handler::Handler { + + typedef osmium::index::multimap::Multimap index_type; + + index_type& m_index_n2w; + index_type& m_index_n2r; + index_type& m_index_w2r; + index_type& m_index_r2r; + + public: + + explicit ObjectRelations(index_type& n2w, index_type& n2r, index_type& w2r, index_type& r2r) : + m_index_n2w(n2w), + m_index_n2r(n2r), + m_index_w2r(w2r), + m_index_r2r(r2r) { + } + + ObjectRelations(const ObjectRelations&) = delete; + ObjectRelations& operator=(const ObjectRelations&) = delete; + + ~ObjectRelations() noexcept = default; + + void way(const osmium::Way& way) { + for (const auto& node_ref : way.nodes()) { + m_index_n2w.set(node_ref.positive_ref(), way.positive_id()); + } + } + + void relation(const osmium::Relation& relation) { + for (const auto& member : relation.members()) { + switch (member.type()) { + case osmium::item_type::node: + m_index_n2r.set(member.positive_ref(), relation.positive_id()); + break; + case osmium::item_type::way: + m_index_w2r.set(member.positive_ref(), relation.positive_id()); + break; + case osmium::item_type::relation: + m_index_r2r.set(member.positive_ref(), relation.positive_id()); + break; + default: + break; + } + } + } + + }; // class ObjectRelations + + } // namespace handler + +} // namespace osmium + +#endif // OSMIUM_HANDLER_OBJECT_RELATIONS_HPP diff --git a/ThirdParty/osmium/index/detail/mmap_vector_anon.hpp b/ThirdParty/osmium/index/detail/mmap_vector_anon.hpp new file mode 100644 index 000000000..f06696150 --- /dev/null +++ b/ThirdParty/osmium/index/detail/mmap_vector_anon.hpp @@ -0,0 +1,78 @@ +#ifndef OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP +#define OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#ifdef __linux__ + +#include + +#include +#include + +namespace osmium { + + namespace detail { + + /** + * This class looks and behaves like STL vector, but uses mmap internally. + */ + template + class mmap_vector_anon : public mmap_vector_base { + + public: + + mmap_vector_anon() : + mmap_vector_base( + -1, + osmium::detail::mmap_vector_size_increment, + 0, + osmium::detail::typed_mmap::map(osmium::detail::mmap_vector_size_increment)) { + } + + void reserve(size_t new_capacity) { + if (new_capacity > this->capacity()) { + this->data(osmium::detail::typed_mmap::remap(this->data(), this->capacity(), new_capacity)); + this->m_capacity = new_capacity; + } + } + + }; // class mmap_vector_anon + + } // namespace detail + +} // namespace osmium + +#endif // __linux__ + +#endif // OSMIUM_DETAIL_MMAP_VECTOR_ANON_HPP diff --git a/ThirdParty/osmium/index/detail/mmap_vector_base.hpp b/ThirdParty/osmium/index/detail/mmap_vector_base.hpp new file mode 100644 index 000000000..7ff4af2ba --- /dev/null +++ b/ThirdParty/osmium/index/detail/mmap_vector_base.hpp @@ -0,0 +1,183 @@ +#ifndef OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP +#define OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include + +namespace osmium { + + namespace detail { + + constexpr size_t mmap_vector_size_increment = 1024 * 1024; + + /** + * This is a base class for implementing classes that look like + * STL vector but use mmap internally. This class can not be used + * on it's own. Use the derived classes mmap_vector_anon or + * mmap_vector_file. + */ + template class TDerived> + class mmap_vector_base { + + protected: + + int m_fd; + size_t m_capacity; + size_t m_size; + T* m_data; + + explicit mmap_vector_base(int fd, size_t capacity, size_t size, T* data) : + m_fd(fd), + m_capacity(capacity), + m_size(size), + m_data(data) { + } + + explicit mmap_vector_base(int fd, size_t capacity, size_t size) : + m_fd(fd), + m_capacity(capacity), + m_size(size), + m_data(osmium::detail::typed_mmap::grow_and_map(capacity, m_fd)) { + } + + void data(T* data) { + m_data = data; + } + + public: + + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef T* iterator; + typedef const T* const_iterator; + + ~mmap_vector_base() { + osmium::detail::typed_mmap::unmap(m_data, m_capacity); + } + + size_t capacity() const { + return m_capacity; + } + + size_t size() const { + return m_size; + } + + bool empty() const { + return m_size == 0; + } + + const T* data() const { + return m_data; + } + + T* data() { + return m_data; + } + + T& operator[](size_t n) { + return m_data[n]; + } + + T at(size_t n) const { + if (n >= m_size) { + throw std::out_of_range("out of range"); + } + return m_data[n]; + } + + void clear() { + m_size = 0; + } + + void shrink_to_fit() { + // XXX do something here + } + + void push_back(const T& value) { + if (m_size >= m_capacity) { + resize(m_size+1); + } + m_data[m_size] = value; + ++m_size; + } + + void resize(size_t new_size) { + if (new_size > this->capacity()) { + static_cast*>(this)->reserve(new_size + osmium::detail::mmap_vector_size_increment); + } + if (new_size > this->size()) { + new (this->data() + this->size()) T[new_size - this->size()]; + } + this->m_size = new_size; + } + + iterator begin() { + return m_data; + } + + iterator end() { + return m_data + m_size; + } + + const_iterator begin() const { + return m_data; + } + + const_iterator end() const { + return m_data + m_size; + } + + const_iterator cbegin() { + return m_data; + } + + const_iterator cend() { + return m_data + m_size; + } + + }; // class mmap_vector_base + + } // namespace detail + +} // namespace osmium + +#endif // OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP diff --git a/ThirdParty/osmium/index/detail/mmap_vector_file.hpp b/ThirdParty/osmium/index/detail/mmap_vector_file.hpp new file mode 100644 index 000000000..fe2f98a9e --- /dev/null +++ b/ThirdParty/osmium/index/detail/mmap_vector_file.hpp @@ -0,0 +1,83 @@ +#ifndef OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP +#define OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +#include +#include +#include + +namespace osmium { + + namespace detail { + + /** + * This class looks and behaves like STL vector, but mmap's a file internally. + */ + template + class mmap_vector_file : public mmap_vector_base { + + public: + + explicit mmap_vector_file() : + mmap_vector_base( + osmium::detail::create_tmp_file(), + osmium::detail::mmap_vector_size_increment, + 0) { + } + + explicit mmap_vector_file(int fd) : + mmap_vector_base( + fd, + osmium::detail::typed_mmap::file_size(fd) == 0 ? osmium::detail::mmap_vector_size_increment : osmium::detail::typed_mmap::file_size(fd), + osmium::detail::typed_mmap::file_size(fd)) { + } + + void reserve(size_t new_capacity) { + if (new_capacity > this->capacity()) { + osmium::detail::typed_mmap::unmap(this->data(), this->capacity()); + osmium::detail::typed_mmap::grow_file(new_capacity, this->m_fd); + osmium::detail::typed_mmap::map(new_capacity, this->m_fd); + this->m_capacity = new_capacity; + } + } + + }; // class mmap_vector_file + + } // namespace detail + +} // namespace osmium + +#endif // OSMIUM_DETAIL_MMAP_VECTOR_FILE_HPP diff --git a/ThirdParty/osmium/index/detail/tmpfile.hpp b/ThirdParty/osmium/index/detail/tmpfile.hpp new file mode 100644 index 000000000..50c9cc9a5 --- /dev/null +++ b/ThirdParty/osmium/index/detail/tmpfile.hpp @@ -0,0 +1,62 @@ +#ifndef OSMIUM_DETAIL_TMPFILE_HPP +#define OSMIUM_DETAIL_TMPFILE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +namespace osmium { + + namespace detail { + + /** + * Create and open a temporary file. It is removed after opening. + * + * @return File descriptor of temporary file. + * @exception std::system_error if something went wrong. + */ + inline int create_tmp_file() { + FILE* file = ::tmpfile(); + if (!file) { + throw std::system_error(errno, std::system_category(), "tempfile failed"); + } + return fileno(file); + } + + } // namespace detail + +} // namespace osmium + +#endif // OSMIUM_DETAIL_TMPFILE diff --git a/ThirdParty/osmium/index/detail/typed_mmap.hpp b/ThirdParty/osmium/index/detail/typed_mmap.hpp new file mode 100644 index 000000000..d064da2be --- /dev/null +++ b/ThirdParty/osmium/index/detail/typed_mmap.hpp @@ -0,0 +1,227 @@ +#ifndef OSMIUM_DETAIL_TYPED_MMAP_HPP +#define OSMIUM_DETAIL_TYPED_MMAP_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +#ifndef WIN32 +# include +#else +# include +#endif + +#include + +#ifdef _MSC_VER +# define ftruncate _chsize +#else +# include +#endif + +// for bsd systems +#ifndef MAP_ANONYMOUS +# define MAP_ANONYMOUS MAP_ANON +#endif + +namespace osmium { + + /** + * @brief Namespace for Osmium internal use + */ + namespace detail { + + /** + * This is a helper class for working with memory mapped files and + * anonymous shared memory. It wraps the necessary system calls + * adding: + * - error checking: all functions throw exceptions where needed + * - internal casts and size calculations allow use with user defined + * type T instead of void* + * + * This class only contains static functions. It should never be + * instantiated. + * + * @tparam T Type of objects we want to store. + */ + template + class typed_mmap { + + public: + + /** + * Create anonymous private memory mapping with enough space for size + * objects of type T. + * + * Note that no constructor is called for any of the objects in this memory! + * + * @param size Number of objects of type T that should fit into this memory + * @return Pointer to mapped memory + * @exception std::system_error If mmap(2) failed + */ + static T* map(size_t size) { + void* addr = ::mmap(nullptr, sizeof(T) * size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" + if (addr == MAP_FAILED) { + throw std::system_error(errno, std::system_category(), "mmap failed"); + } +#pragma GCC diagnostic pop + return reinterpret_cast(addr); + } + + /** + * Create shared memory mapping of a file with enough space for size + * objects of type T. The file must already have at least the + * required size. + * + * Note that no constructor is called for any of the objects in this memory! + * + * @param size Number of objects of type T that should fit into this memory + * @param fd File descriptor + * @param write True if data should be writable + * @return Pointer to mapped memory + * @exception std::system_error If mmap(2) failed + */ + static T* map(size_t size, int fd, bool write = false) { + int prot = PROT_READ; + if (write) { + prot |= PROT_WRITE; + } + void* addr = ::mmap(nullptr, sizeof(T) * size, prot, MAP_SHARED, fd, 0); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" + if (addr == MAP_FAILED) { + throw std::system_error(errno, std::system_category(), "mmap failed"); + } +#pragma GCC diagnostic pop + return reinterpret_cast(addr); + } + +// mremap(2) is only available on linux systems +#ifdef __linux__ + /** + * Grow memory mapping created with map(). + * + * Note that no constructor is called for any of the objects in this memory! + * + * @param data Pointer to current mapping (as returned by typed_mmap()) + * @param old_size Number of objects currently stored in this memory + * @param new_size Number of objects we want to have space for + * @exception std::system_error If mremap(2) call failed + */ + static T* remap(T* data, size_t old_size, size_t new_size) { + void* addr = ::mremap(reinterpret_cast(data), sizeof(T) * old_size, sizeof(T) * new_size, MREMAP_MAYMOVE); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" + if (addr == MAP_FAILED) { + throw std::system_error(errno, std::system_category(), "mremap failed"); + } +#pragma GCC diagnostic pop + return reinterpret_cast(addr); + } +#endif + + /** + * Release memory from map() call. + * + * Note that no destructor is called for the objects in this memory! + * + * @param data Pointer to the data + * @param size Number of objects of type T stored + * @exception std::system_error If munmap(2) call failed + */ + static void unmap(T* data, size_t size) { + if (::munmap(reinterpret_cast(data), sizeof(T) * size) != 0) { + throw std::system_error(errno, std::system_category(), "munmap failed"); + } + } + + /** + * Get number of objects of type T that would fit into a file. + * + * @param fd File descriptor + * @return Number of objects of type T in this file + * @exception std::system_error If fstat(2) call failed + * @exception std::length_error If size of the file isn't a multiple of sizeof(T) + */ + static size_t file_size(int fd) { + struct stat s; + if (fstat(fd, &s) < 0) { + throw std::system_error(errno, std::system_category(), "fstat failed"); + } + if (s.st_size % sizeof(T) != 0) { + throw std::length_error("file size has to be multiple of object size"); + } + return s.st_size / sizeof(T); + } + + /** + * Grow file so there is enough space for at least new_size objects + * of type T. If the file is large enough already, nothing is done. + * The file is never shrunk. + * + * @param new_size Number of objects of type T that should fit into this file + * @param fd File descriptor + * @exception std::system_error If ftruncate(2) call failed + */ + static void grow_file(size_t new_size, int fd) { + if (file_size(fd) < new_size) { + if (::ftruncate(fd, sizeof(T) * new_size) < 0) { + throw std::system_error(errno, std::system_category(), "ftruncate failed"); + } + } + } + + /** + * Grow file to given size (if it is smaller) and mmap it. + * + * @param size Number of objects of type T that should fit into this file + * @param fd File descriptor + * @exception Errors thrown by grow_file() or map() + */ + static T* grow_and_map(size_t size, int fd) { + grow_file(size, fd); + return map(size, fd, true); + } + + }; // class typed_mmap + + } // namespace detail + +} // namespace osmium + +#endif // OSMIUM_DETAIL_TYPED_MMAP_HPP diff --git a/ThirdParty/osmium/index/index.hpp b/ThirdParty/osmium/index/index.hpp new file mode 100644 index 000000000..ece8ec444 --- /dev/null +++ b/ThirdParty/osmium/index/index.hpp @@ -0,0 +1,100 @@ +#ifndef OSMIUM_INDEX_INDEX_HPP +#define OSMIUM_INDEX_INDEX_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include + +#include + +namespace osmium { + + /** + * Exception signaling that an element could not be + * found in an index. + */ + struct not_found : public std::runtime_error { + + not_found(const std::string& what) : + std::runtime_error(what) { + } + + not_found(const char* what) : + std::runtime_error(what) { + } + + }; // struct not_found + + /** + * @brief Indexing of OSM data, Locations, etc. + */ + namespace index { + + template + OSMIUM_NORETURN void not_found_error(TKey key) { + std::stringstream s; + s << "id " << key << " no found"; + throw not_found(s.str()); + } + + /** + * Some of the index classes need an "empty" value that can + * never appear in real data. This function must return this + * empty value for any class used as a value in an index. + * The default implementation returns a default constructed + * object, but it can be specialized. + */ + template + inline constexpr T empty_value() { + return T{}; + } + + /** + * The size_t value in indexes is usually used for offsets + * into a buffer or file. It is unlikely that we ever need + * the full range, so the max value is a good "empty" value. + */ + template <> + inline OSMIUM_CONSTEXPR size_t empty_value() { + return std::numeric_limits::max(); + } + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_INDEX_HPP diff --git a/ThirdParty/osmium/index/map.hpp b/ThirdParty/osmium/index/map.hpp new file mode 100644 index 000000000..df865c727 --- /dev/null +++ b/ThirdParty/osmium/index/map.hpp @@ -0,0 +1,156 @@ +#ifndef OSMIUM_INDEX_MAP_HPP +#define OSMIUM_INDEX_MAP_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include // IWYU pragma: export + +namespace osmium { + + namespace index { + + /** + * @brief Key-value containers with unique integer values for a key + */ + namespace map { + + /** + * This abstract class defines an interface to storage classes + * intended for storing small pieces of data (such as coordinates) + * indexed by a positive integer (such as an object ID). The + * storage must be very space efficient and able to scale to billions + * of objects. + * + * Subclasses have different implementations that store the + * data in different ways in memory and/or on disk. Some storage + * classes are better suited when working with the whole planet, + * some are better for data extracts. + * + * Note that these classes are not required to track "empty" fields. + * When reading data you have to be sure you have put something in + * there before. + * + * A typical use for this and derived classes is storage of node + * locations indexed by node ID. These indexes will only work + * on 64 bit systems if used in this case. 32 bit systems just + * can't address that much memory! + * + * @tparam TId Id type, usually osmium::unsigned_object_id_type, + * must be an unsigned integral type. + * @tparam TValue Value type, usually osmium::Location or size_t. + * Copied by value, so should be "small" type. + */ + template + class Map { + + static_assert(std::is_integral::value && std::is_unsigned::value, + "TId template parameter for class Map must be unsigned integral type"); + + Map(const Map&) = delete; + Map& operator=(const Map&) = delete; + + protected: + + Map(Map&&) = default; + Map& operator=(Map&&) = default; + + public: + + /// The "key" type, usually osmium::unsigned_object_id_type. + typedef TId key_type; + + /// The "value" type, usually a Location or size_t. + typedef TValue value_type; + + Map() = default; + +// workaround for a bug in GCC 4.7 +#if __GNUC__ == 4 && __GNUC_MINOR__ < 8 + virtual ~Map() {} +#else + virtual ~Map() = default; +#endif + + virtual void reserve(const size_t) { + // default implementation is empty + } + + /// Set the field with id to value. + virtual void set(const TId id, const TValue value) = 0; + + /// Retrieve value by id. Does not check for overflow or empty fields. + virtual const TValue get(const TId id) const = 0; + + /** + * Get the approximate number of items in the storage. The storage + * might allocate memory in blocks, so this size might not be + * accurate. You can not use this to find out how much memory the + * storage uses. Use used_memory() for that. + */ + virtual size_t size() const = 0; + + /** + * Get the memory used for this storage in bytes. Note that this + * is not necessarily entirely accurate but an approximation. + * For storage classes that store the data in memory, this is + * the main memory used, for storage classes storing data on disk + * this is the memory used on disk. + */ + virtual size_t used_memory() const = 0; + + /** + * Clear memory used for this storage. After this you can not + * use the storage container any more. + */ + virtual void clear() = 0; + + /** + * Sort data in map. Call this after writing all data and + * before reading. Not all implementations need this. + */ + virtual void sort() { + // default implementation is empty + } + + }; // class Map + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MAP_HPP diff --git a/ThirdParty/osmium/index/map/dummy.hpp b/ThirdParty/osmium/index/map/dummy.hpp new file mode 100644 index 000000000..b3239e81b --- /dev/null +++ b/ThirdParty/osmium/index/map/dummy.hpp @@ -0,0 +1,87 @@ +#ifndef OSMIUM_INDEX_MAP_DUMMY_HPP +#define OSMIUM_INDEX_MAP_DUMMY_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +#include + +namespace osmium { + + namespace index { + + namespace map { + + /** + * Pseudo map. + * Use this class if you don't need a map, but you + * need an object that behaves like one. + */ + template + class Dummy : public osmium::index::map::Map { + + public: + + Dummy() = default; + + ~Dummy() override final = default; + + void set(const TId, const TValue) override final { + // intentionally left blank + } + + const TValue get(const TId id) const override final { + not_found_error(id); + } + + size_t size() const override final { + return 0; + } + + size_t used_memory() const override final { + return 0; + } + + void clear() override final { + } + + }; // class Dummy + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MAP_DUMMY_HPP diff --git a/ThirdParty/osmium/index/map/mmap_vector_anon.hpp b/ThirdParty/osmium/index/map/mmap_vector_anon.hpp new file mode 100644 index 000000000..863de2a72 --- /dev/null +++ b/ThirdParty/osmium/index/map/mmap_vector_anon.hpp @@ -0,0 +1,61 @@ +#ifndef OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP +#define OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#ifdef __linux__ + +#include +#include + +namespace osmium { + + namespace index { + + namespace map { + + template + using DenseMapMmap = VectorBasedDenseMap, TId, TValue>; + + template + using SparseMapMmap = VectorBasedSparseMap; + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // __linux__ + +#endif // OSMIUM_INDEX_MAP_MMAP_VECTOR_ANON_HPP diff --git a/ThirdParty/osmium/index/map/mmap_vector_file.hpp b/ThirdParty/osmium/index/map/mmap_vector_file.hpp new file mode 100644 index 000000000..7d178446d --- /dev/null +++ b/ThirdParty/osmium/index/map/mmap_vector_file.hpp @@ -0,0 +1,57 @@ +#ifndef OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP +#define OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +namespace osmium { + + namespace index { + + namespace map { + + template + using DenseMapFile = VectorBasedDenseMap, TId, TValue>; + + template + using SparseMapFile = VectorBasedSparseMap; + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MAP_MMAP_VECTOR_FILE_HPP diff --git a/ThirdParty/osmium/index/map/sparse_table.hpp b/ThirdParty/osmium/index/map/sparse_table.hpp new file mode 100644 index 000000000..21eb6681d --- /dev/null +++ b/ThirdParty/osmium/index/map/sparse_table.hpp @@ -0,0 +1,140 @@ +#ifndef OSMIUM_INDEX_MAP_SPARSE_TABLE_HPP +#define OSMIUM_INDEX_MAP_SPARSE_TABLE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +#include + +#include +#include + +namespace osmium { + + namespace index { + + namespace map { + + /** + * The SparseTable index stores elements in a Google sparsetable, + * a data structure that can hold sparsly filled tables in a + * very space efficient way. It will resize automatically. + * + * Use this index if the ID space is only sparsly + * populated, such as when working with smaller OSM files (like + * country extracts). + * + * This will only work on 64 bit machines. + */ + template + class SparseTable : public osmium::index::map::Map { + + TId m_grow_size; + + google::sparsetable m_elements; + + static_assert(sizeof(typename google::sparsetable::size_type) >= 8, "google::sparsetable needs 64bit machine"); + + public: + + /** + * Constructor. + * + * @param grow_size The initial size of the index (ie number of + * elements that fit into the index). + * The storage will grow by at least this size + * every time it runs out of space. + */ + explicit SparseTable(const TId grow_size=10000) : + m_grow_size(grow_size), + m_elements(grow_size) { + } + + ~SparseTable() override final = default; + + void set(const TId id, const TValue value) override final { + if (id >= m_elements.size()) { + m_elements.resize(id + m_grow_size); + } + m_elements[id] = value; + } + + const TValue get(const TId id) const override final { + if (id >= m_elements.size()) { + not_found_error(id); + } + if (m_elements[id] == osmium::index::empty_value()) { + not_found_error(id); + } + return m_elements[id]; + } + + size_t size() const override final { + return m_elements.size(); + } + + size_t used_memory() const override final { + // unused elements use 1 bit, used elements sizeof(TValue) bytes + // http://google-sparsehash.googlecode.com/svn/trunk/doc/sparsetable.html + return (m_elements.size() / 8) + (m_elements.num_nonempty() * sizeof(TValue)); + } + + void clear() override final { + m_elements.clear(); + } + + void dump_as_list(const int fd) const { + std::vector> v; + int n=0; + for (const TValue value : m_elements) { + if (value != osmium::index::empty_value()) { + v.emplace_back(n, value); + } + ++n; + } + osmium::io::detail::reliable_write(fd, reinterpret_cast(v.data()), sizeof(std::pair) * v.size()); + } + + }; // class SparseTable + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_BYID_SPARSE_TABLE_HPP diff --git a/ThirdParty/osmium/index/map/stl_map.hpp b/ThirdParty/osmium/index/map/stl_map.hpp new file mode 100644 index 000000000..08458d55e --- /dev/null +++ b/ThirdParty/osmium/index/map/stl_map.hpp @@ -0,0 +1,112 @@ +#ifndef OSMIUM_INDEX_MAP_STL_MAP_HPP +#define OSMIUM_INDEX_MAP_STL_MAP_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace index { + + namespace map { + + /** + * This implementation uses std::map internally. It uses rather a + * lot of memory, but might make sense for small maps. + */ + template + class StlMap : public osmium::index::map::Map { + + // This is a rough estimate for the memory needed for each + // element in the map (id + value + pointers to left, right, + // and parent plus some overhead for color of red-black-tree + // or similar). + static constexpr size_t element_size = sizeof(TId) + sizeof(TValue) + sizeof(void*) * 4; + + std::map m_elements; + + public: + + StlMap() = default; + + ~StlMap() override final = default; + + void set(const TId id, const TValue value) override final { + m_elements[id] = value; + } + + const TValue get(const TId id) const override final { + try { + return m_elements.at(id); + } catch (std::out_of_range&) { + not_found_error(id); + } + } + + size_t size() const override final { + return m_elements.size(); + } + + size_t used_memory() const override final { + return element_size * m_elements.size(); + } + + void clear() override final { + m_elements.clear(); + } + + void dump_as_list(const int fd) const { + typedef typename std::map::value_type t; + std::vector v; + std::copy(m_elements.begin(), m_elements.end(), std::back_inserter(v)); + osmium::io::detail::reliable_write(fd, reinterpret_cast(v.data()), sizeof(t) * v.size()); + } + + }; // class StlMap + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MAP_STL_MAP_HPP diff --git a/ThirdParty/osmium/index/map/stl_vector.hpp b/ThirdParty/osmium/index/map/stl_vector.hpp new file mode 100644 index 000000000..238e9afa9 --- /dev/null +++ b/ThirdParty/osmium/index/map/stl_vector.hpp @@ -0,0 +1,61 @@ +#ifndef OSMIUM_INDEX_MAP_STL_VECTOR_HPP +#define OSMIUM_INDEX_MAP_STL_VECTOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +#include + +namespace osmium { + + namespace index { + + namespace map { + + template + using DenseMapMem = VectorBasedDenseMap, TId, TValue>; + + template + using StdVectorWrap = std::vector; + + template + using SparseMapMem = VectorBasedSparseMap; + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MAP_STL_VECTOR_HPP diff --git a/ThirdParty/osmium/index/map/vector.hpp b/ThirdParty/osmium/index/map/vector.hpp new file mode 100644 index 000000000..3e4890024 --- /dev/null +++ b/ThirdParty/osmium/index/map/vector.hpp @@ -0,0 +1,208 @@ +#ifndef OSMIUM_INDEX_MAP_VECTOR_HPP +#define OSMIUM_INDEX_MAP_VECTOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace index { + + namespace map { + + template + class VectorBasedDenseMap : public Map { + + TVector m_vector; + + public: + + VectorBasedDenseMap() : + m_vector() { + } + + explicit VectorBasedDenseMap(int fd) : + m_vector(fd) { + } + + ~VectorBasedDenseMap() {} + + void reserve(const size_t size) override final { + m_vector.reserve(size); + } + + void set(const TId id, const TValue value) override final { + if (size() <= id) { + m_vector.resize(id+1); + } + m_vector[id] = value; + } + + const TValue get(const TId id) const override final { + try { + const TValue& value = m_vector.at(id); + if (value == osmium::index::empty_value()) { + not_found_error(id); + } + return value; + } catch (std::out_of_range&) { + not_found_error(id); + } + } + + size_t size() const override final { + return m_vector.size(); + } + + size_t used_memory() const override final { + return sizeof(TValue) * size(); + } + + void clear() override final { + m_vector.clear(); + m_vector.shrink_to_fit(); + } + + }; // class VectorBasedDenseMap + + + template class TVector> + class VectorBasedSparseMap : public Map { + + public: + + typedef typename std::pair element_type; + typedef TVector vector_type; + typedef typename vector_type::iterator iterator; + typedef typename vector_type::const_iterator const_iterator; + + private: + + vector_type m_vector; + + public: + + VectorBasedSparseMap() : + m_vector() { + } + + VectorBasedSparseMap(int fd) : + m_vector(fd) { + } + + ~VectorBasedSparseMap() override final = default; + + void set(const TId id, const TValue value) override final { + m_vector.push_back(element_type(id, value)); + } + + const TValue get(const TId id) const override final { + const element_type element { + id, + osmium::index::empty_value() + }; + const auto result = std::lower_bound(m_vector.begin(), m_vector.end(), element, [](const element_type& a, const element_type& b) { + return a.first < b.first; + }); + if (result == m_vector.end() || result->first != id) { + not_found_error(id); + } else { + return result->second; + } + } + + size_t size() const override final { + return m_vector.size(); + } + + size_t byte_size() const { + return m_vector.size() * sizeof(element_type); + } + + size_t used_memory() const override final { + return sizeof(element_type) * size(); + } + + void clear() override final { + m_vector.clear(); + m_vector.shrink_to_fit(); + } + + void sort() override final { + std::sort(m_vector.begin(), m_vector.end()); + } + + void dump_as_list(int fd) const { + osmium::io::detail::reliable_write(fd, reinterpret_cast(m_vector.data()), byte_size()); + } + + iterator begin() { + return m_vector.begin(); + } + + iterator end() { + return m_vector.end(); + } + + const_iterator cbegin() const { + return m_vector.cbegin(); + } + + const_iterator cend() const { + return m_vector.cend(); + } + + const_iterator begin() const { + return m_vector.cbegin(); + } + + const_iterator end() const { + return m_vector.cend(); + } + + }; // class VectorBasedSparseMap + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MAP_VECTOR_HPP diff --git a/ThirdParty/osmium/index/multimap.hpp b/ThirdParty/osmium/index/multimap.hpp new file mode 100644 index 000000000..bf20dfb26 --- /dev/null +++ b/ThirdParty/osmium/index/multimap.hpp @@ -0,0 +1,125 @@ +#ifndef OSMIUM_INDEX_MULTIMAP_HPP +#define OSMIUM_INDEX_MULTIMAP_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include // IWYU pragma: export + +namespace osmium { + + namespace index { + + /** + * @brief Key-value containers with multiple values for an integer key + */ + namespace multimap { + + template + class Multimap { + + static_assert(std::is_integral::value && std::is_unsigned::value, + "TId template parameter for class Multimap must be unsigned integral type"); + + typedef typename std::pair element_type; + + Multimap(const Multimap&) = delete; + Multimap& operator=(const Multimap&) = delete; + + protected: + + Multimap(Multimap&&) = default; + Multimap& operator=(Multimap&&) = default; + + public: + + /// The "key" type, usually osmium::unsigned_object_id_type. + typedef TId key_type; + + /// The "value" type, usually a Location or size_t. + typedef TValue value_type; + + Multimap() = default; + + virtual ~Multimap() noexcept = default; + + /// Set the field with id to value. + virtual void set(const TId id, const TValue value) = 0; + + typedef element_type* iterator; + +// virtual std::pair get_all(const TId id) const = 0; + + /** + * Get the approximate number of items in the storage. The storage + * might allocate memory in blocks, so this size might not be + * accurate. You can not use this to find out how much memory the + * storage uses. Use used_memory() for that. + */ + virtual size_t size() const = 0; + + /** + * Get the memory used for this storage in bytes. Note that this + * is not necessarily entirely accurate but an approximation. + * For storage classes that store the data in memory, this is + * the main memory used, for storage classes storing data on disk + * this is the memory used on disk. + */ + virtual size_t used_memory() const = 0; + + /** + * Clear memory used for this storage. After this you can not + * use the storage container any more. + */ + virtual void clear() = 0; + + /** + * Sort data in map. Call this after writing all data and + * before reading. Not all implementations need this. + */ + virtual void sort() { + // default implementation is empty + } + + }; // class Multimap + + } // namespace map + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MULTIMAP_HPP diff --git a/ThirdParty/osmium/index/multimap/hybrid.hpp b/ThirdParty/osmium/index/multimap/hybrid.hpp new file mode 100644 index 000000000..4214adc4e --- /dev/null +++ b/ThirdParty/osmium/index/multimap/hybrid.hpp @@ -0,0 +1,199 @@ +#ifndef OSMIUM_INDEX_MULTIMAP_HYBRID_HPP +#define OSMIUM_INDEX_MULTIMAP_HYBRID_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include +#include +#include + +namespace osmium { + + namespace index { + + namespace multimap { + + template + class HybridIterator { + + typedef SparseMultimapMem main_map_type; + typedef StlMultimap extra_map_type; + + typedef typename std::pair element_type; + + typename main_map_type::iterator m_begin_main; + typename main_map_type::iterator m_end_main; + typename extra_map_type::iterator m_begin_extra; + typename extra_map_type::iterator m_end_extra; + + public: + + explicit HybridIterator(typename main_map_type::iterator begin_main, + typename main_map_type::iterator end_main, + typename extra_map_type::iterator begin_extra, + typename extra_map_type::iterator end_extra) : + m_begin_main(begin_main), + m_end_main(end_main), + m_begin_extra(begin_extra), + m_end_extra(end_extra) { + } + + HybridIterator& operator++() { + if (m_begin_main == m_end_main) { + ++m_begin_extra; + } else { + ++m_begin_main; + while (m_begin_main != m_end_main && m_begin_main->second == osmium::index::empty_value()) { // ignore removed elements + ++m_begin_main; + } + } + return *this; + } + + HybridIterator operator++(int) { + auto tmp(*this); + operator++(); + return tmp; + } + + bool operator==(const HybridIterator& rhs) const { + return m_begin_main == rhs.m_begin_main && + m_end_main == rhs.m_end_main && + m_begin_extra == rhs.m_begin_extra && + m_end_extra == rhs.m_end_extra; + } + + bool operator!=(const HybridIterator& rhs) const { + return ! operator==(rhs); + } + + const element_type& operator*() { + if (m_begin_main == m_end_main) { + return *m_begin_extra; + } else { + return *m_begin_main; + } + } + + const element_type* operator->() { + return &operator*(); + } + + }; + + template + class Hybrid : public Multimap { + + typedef SparseMultimapMem main_map_type; + typedef StlMultimap extra_map_type; + + main_map_type m_main; + extra_map_type m_extra; + + public: + + typedef HybridIterator iterator; + typedef const HybridIterator const_iterator; + + Hybrid() : + m_main(), + m_extra() { + } + + size_t size() const override final { + return m_main.size() + m_extra.size(); + } + + size_t used_memory() const override final { + return m_main.used_memory() + m_extra.used_memory(); + } + + void reserve(const size_t size) { + m_main.reserve(size); + } + + void unsorted_set(const TId id, const TValue value) { + m_main.set(id, value); + } + + void set(const TId id, const TValue value) override final { + m_extra.set(id, value); + } + + std::pair get_all(const TId id) { + auto result_main = m_main.get_all(id); + auto result_extra = m_extra.get_all(id); + return std::make_pair(iterator(result_main.first, result_main.second, result_extra.first, result_extra.second), + iterator(result_main.second, result_main.second, result_extra.second, result_extra.second)); + } + + void remove(const TId id, const TValue value) { + m_main.remove(id, value); + m_extra.remove(id, value); + } + + void consolidate() { + m_main.erase_removed(); + for (const auto& element : m_extra) { + m_main.set(element.first, element.second); + } + m_extra.clear(); + m_main.sort(); + } + + void dump_as_list(int fd) { + consolidate(); + m_main.dump_as_list(fd); + } + + void clear() override final { + m_main.clear(); + m_extra.clear(); + } + + void sort() override final { + m_main.sort(); + } + + }; // Hybrid + + } // namespace multimap + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MULTIMAP_HYBRID_HPP diff --git a/ThirdParty/osmium/index/multimap/mmap_vector_anon.hpp b/ThirdParty/osmium/index/multimap/mmap_vector_anon.hpp new file mode 100644 index 000000000..defb1eb37 --- /dev/null +++ b/ThirdParty/osmium/index/multimap/mmap_vector_anon.hpp @@ -0,0 +1,58 @@ +#ifndef OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP +#define OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#ifdef __linux__ + +#include +#include + +namespace osmium { + + namespace index { + + namespace multimap { + + template + using SparseMultimapMmap = VectorBasedSparseMultimap; + + } // namespace multimap + + } // namespace index + +} // namespace osmium + +#endif // __linux__ + +#endif // OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_ANON_HPP diff --git a/ThirdParty/osmium/index/multimap/mmap_vector_file.hpp b/ThirdParty/osmium/index/multimap/mmap_vector_file.hpp new file mode 100644 index 000000000..b9b40ae4f --- /dev/null +++ b/ThirdParty/osmium/index/multimap/mmap_vector_file.hpp @@ -0,0 +1,54 @@ +#ifndef OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP +#define OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +namespace osmium { + + namespace index { + + namespace multimap { + + template + using SparseMultimapFile = VectorBasedSparseMultimap; + + } // namespace multimap + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MULTIMAP_MMAP_VECTOR_FILE_HPP diff --git a/ThirdParty/osmium/index/multimap/stl_multimap.hpp b/ThirdParty/osmium/index/multimap/stl_multimap.hpp new file mode 100644 index 000000000..cd19c1560 --- /dev/null +++ b/ThirdParty/osmium/index/multimap/stl_multimap.hpp @@ -0,0 +1,151 @@ +#ifndef OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP +#define OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace index { + + namespace multimap { + + /** + * This implementation uses std::multimap internally. It uses rather a + * lot of memory, but might make sense for small maps. + */ + template + class StlMultimap : public osmium::index::multimap::Multimap { + + // This is a rough estimate for the memory needed for each + // element in the map (id + value + pointers to left, right, + // and parent plus some overhead for color of red-black-tree + // or similar). + static constexpr size_t element_size = sizeof(TId) + sizeof(TValue) + sizeof(void*) * 4; + + public: + + typedef typename std::multimap collection_type; + typedef typename collection_type::iterator iterator; + typedef typename collection_type::const_iterator const_iterator; + typedef typename collection_type::value_type value_type; + + typedef typename std::pair element_type; + + private: + + collection_type m_elements; + + public: + + StlMultimap() = default; + + ~StlMultimap() noexcept override final = default; + + void unsorted_set(const TId id, const TValue value) { + m_elements.emplace(id, value); + } + + void set(const TId id, const TValue value) override final { + m_elements.emplace(id, value); + } + + std::pair get_all(const TId id) { + return m_elements.equal_range(id); + } + + std::pair get_all(const TId id) const { + return m_elements.equal_range(id); + } + + void remove(const TId id, const TValue value) { + std::pair r = get_all(id); + for (iterator it = r.first; it != r.second; ++it) { + if (it->second == value) { + m_elements.erase(it); + return; + } + } + } + + iterator begin() { + return m_elements.begin(); + } + + iterator end() { + return m_elements.end(); + } + + size_t size() const override final { + return m_elements.size(); + } + + size_t used_memory() const override final { + return element_size * m_elements.size(); + } + + void clear() override final { + m_elements.clear(); + } + + void consolidate() { + // intentionally left blank + } + + void dump_as_list(const int fd) const { + std::vector v; + for (const auto& element : m_elements) { + v.emplace_back(element.first, element.second); + } +// std::copy(m_elements.cbegin(), m_elements.cend(), std::back_inserter(v)); + std::sort(v.begin(), v.end()); + osmium::io::detail::reliable_write(fd, reinterpret_cast(v.data()), sizeof(element_type) * v.size()); + } + + }; // class StlMultimap + + } // namespace multimap + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP diff --git a/ThirdParty/osmium/index/multimap/stl_vector.hpp b/ThirdParty/osmium/index/multimap/stl_vector.hpp new file mode 100644 index 000000000..2102824d5 --- /dev/null +++ b/ThirdParty/osmium/index/multimap/stl_vector.hpp @@ -0,0 +1,58 @@ +#ifndef OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP +#define OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +#include + +namespace osmium { + + namespace index { + + namespace multimap { + + template + using StdVectorWrap = std::vector; + + template + using SparseMultimapMem = VectorBasedSparseMultimap; + + } // namespace multimap + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MULTIMAP_STL_VECTOR_HPP diff --git a/ThirdParty/osmium/index/multimap/vector.hpp b/ThirdParty/osmium/index/multimap/vector.hpp new file mode 100644 index 000000000..1a548a814 --- /dev/null +++ b/ThirdParty/osmium/index/multimap/vector.hpp @@ -0,0 +1,141 @@ +#ifndef OSMIUM_INDEX_MULTIMAP_VECTOR_HPP +#define OSMIUM_INDEX_MULTIMAP_VECTOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace index { + + namespace multimap { + + template class TVector> + class VectorBasedSparseMultimap : public Multimap { + + public: + + typedef typename std::pair element_type; + typedef TVector vector_type; + typedef typename vector_type::iterator iterator; + typedef typename vector_type::const_iterator const_iterator; + + private: + + vector_type m_vector; + + static bool is_removed(element_type& element) { + return element.second == osmium::index::empty_value(); + } + + public: + + void set(const TId id, const TValue value) override final { + m_vector.push_back(element_type(id, value)); + } + + void unsorted_set(const TId id, const TValue value) { + m_vector.push_back(element_type(id, value)); + } + + std::pair get_all(const TId id) { + const element_type element { + id, + osmium::index::empty_value() + }; + return std::equal_range(m_vector.begin(), m_vector.end(), element, [](const element_type& a, const element_type& b) { + return a.first < b.first; + }); + } + + size_t size() const override final { + return m_vector.size(); + } + + size_t byte_size() const { + return m_vector.size() * sizeof(element_type); + } + + size_t used_memory() const override final { + return sizeof(element_type) * size(); + } + + void clear() override final { + m_vector.clear(); + m_vector.shrink_to_fit(); + } + + void sort() override final { + std::sort(m_vector.begin(), m_vector.end()); + } + + void remove(const TId id, const TValue value) { + auto r = get_all(id); + for (auto it = r.first; it != r.second; ++it) { + if (it->second == value) { + it->second = 0; + return; + } + } + } + + void consolidate() { + std::sort(m_vector.begin(), m_vector.end()); + } + + void erase_removed() { + m_vector.erase( + std::remove_if(m_vector.begin(), m_vector.end(), is_removed), + m_vector.end() + ); + } + + void dump_as_list(int fd) const { + osmium::io::detail::reliable_write(fd, reinterpret_cast(m_vector.data()), byte_size()); + } + + }; // class VectorBasedSparseMultimap + + } // namespace multimap + + } // namespace index + +} // namespace osmium + +#endif // OSMIUM_INDEX_MULTIMAP_VECTOR_HPP diff --git a/ThirdParty/osmium/io/any_compression.hpp b/ThirdParty/osmium/io/any_compression.hpp new file mode 100644 index 000000000..03ad5ce2b --- /dev/null +++ b/ThirdParty/osmium/io/any_compression.hpp @@ -0,0 +1,39 @@ +#ifndef OSMIUM_IO_ANY_COMPRESSION_HPP +#define OSMIUM_IO_ANY_COMPRESSION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_ANY_COMPRESSION_HPP diff --git a/ThirdParty/osmium/io/any_input.hpp b/ThirdParty/osmium/io/any_input.hpp new file mode 100644 index 000000000..f60ff1455 --- /dev/null +++ b/ThirdParty/osmium/io/any_input.hpp @@ -0,0 +1,41 @@ +#ifndef OSMIUM_IO_ANY_INPUT_HPP +#define OSMIUM_IO_ANY_INPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include // IWYU pragma: export + +#include // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_ANY_INPUT_HPP diff --git a/ThirdParty/osmium/io/any_output.hpp b/ThirdParty/osmium/io/any_output.hpp new file mode 100644 index 000000000..9d97d7d93 --- /dev/null +++ b/ThirdParty/osmium/io/any_output.hpp @@ -0,0 +1,42 @@ +#ifndef OSMIUM_IO_ANY_OUTPUT_HPP +#define OSMIUM_IO_ANY_OUTPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include // IWYU pragma: export + +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_ANY_OUTPUT_HPP diff --git a/ThirdParty/osmium/io/bzip2_compression.hpp b/ThirdParty/osmium/io/bzip2_compression.hpp new file mode 100644 index 000000000..1b6552528 --- /dev/null +++ b/ThirdParty/osmium/io/bzip2_compression.hpp @@ -0,0 +1,196 @@ +#ifndef OSMIUM_IO_BZIP2_COMPRESSION_HPP +#define OSMIUM_IO_BZIP2_COMPRESSION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#define OSMIUM_LINK_WITH_LIBS_BZ2LIB -lbz2 + +#include +#include +#include + +#include +#ifndef _MSC_VER +# include +#endif + +#include +#include +#include + +namespace osmium { + + namespace io { + + namespace detail { + + OSMIUM_NORETURN inline void throw_bzip2_error(const std::string& msg, int error) { + throw std::runtime_error("bzip2 error: " + msg + ": " + std::to_string(error)); + } + + } // namespace detail + + class Bzip2Compressor : public Compressor { + + FILE* m_file; + int m_bzerror; + BZFILE* m_bzfile; + + public: + + explicit Bzip2Compressor(int fd) : + Compressor(), + m_file(fdopen(dup(fd), "wb")), + m_bzerror(BZ_OK), + m_bzfile(::BZ2_bzWriteOpen(&m_bzerror, m_file, 6, 0, 0)) { + if (!m_bzfile) { + detail::throw_bzip2_error("write open failed", m_bzerror); + } + } + + ~Bzip2Compressor() override final { + this->close(); + } + + void write(const std::string& data) override final { + int error; + ::BZ2_bzWrite(&error, m_bzfile, const_cast(data.data()), data.size()); + if (error != BZ_OK && error != BZ_STREAM_END) { + detail::throw_bzip2_error("write failed", error); + } + } + + void close() override final { + if (m_bzfile) { + int error; + ::BZ2_bzWriteClose(&error, m_bzfile, 0, nullptr, nullptr); + m_bzfile = nullptr; + if (m_file) { + fclose(m_file); + } + if (error != BZ_OK) { + detail::throw_bzip2_error("write close failed", error); + } + } + } + + }; // class Bzip2Compressor + + class Bzip2Decompressor : public Decompressor { + + FILE* m_file; + int m_bzerror; + BZFILE* m_bzfile; + bool m_stream_end {false}; + + public: + + Bzip2Decompressor(int fd) : + Decompressor(), + m_file(fdopen(dup(fd), "rb")), + m_bzerror(BZ_OK), + m_bzfile(::BZ2_bzReadOpen(&m_bzerror, m_file, 0, 0, nullptr, 0)) { + if (!m_bzfile) { + detail::throw_bzip2_error("read open failed", m_bzerror); + } + } + + ~Bzip2Decompressor() override final { + this->close(); + } + + std::string read() override final { + if (m_stream_end) { + return std::string(); + } + std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0'); + int error; + int nread = ::BZ2_bzRead(&error, m_bzfile, const_cast(buffer.data()), buffer.size()); + if (error != BZ_OK && error != BZ_STREAM_END) { + detail::throw_bzip2_error("read failed", error); + } + if (error == BZ_STREAM_END) { + void* unused; + int nunused; + if (! feof(m_file)) { + ::BZ2_bzReadGetUnused(&error, m_bzfile, &unused, &nunused); + if (error != BZ_OK) { + detail::throw_bzip2_error("get unused failed", error); + } + std::string unused_data(static_cast(unused), static_cast(nunused)); + ::BZ2_bzReadClose(&error, m_bzfile); + if (error != BZ_OK) { + detail::throw_bzip2_error("read close failed", error); + } + m_bzfile = ::BZ2_bzReadOpen(&error, m_file, 0, 0, const_cast(static_cast(unused_data.data())), unused_data.size()); + if (error != BZ_OK) { + detail::throw_bzip2_error("read open failed", error); + } + } else { + m_stream_end = true; + } + } + buffer.resize(static_cast(nread)); + return buffer; + } + + void close() override final { + if (m_bzfile) { + int error; + ::BZ2_bzReadClose(&error, m_bzfile); + m_bzfile = nullptr; + if (m_file) { + fclose(m_file); + } + if (error != BZ_OK) { + detail::throw_bzip2_error("read close failed", error); + } + } + } + + }; // class Bzip2Decompressor + + namespace { + + const bool registered_bzip2_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::bzip2, + [](int fd) { return new osmium::io::Bzip2Compressor(fd); }, + [](int fd) { return new osmium::io::Bzip2Decompressor(fd); } + ); + + } // anonymous namespace + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_BZIP2_COMPRESSION_HPP diff --git a/ThirdParty/osmium/io/compression.hpp b/ThirdParty/osmium/io/compression.hpp new file mode 100644 index 000000000..5ac242ab0 --- /dev/null +++ b/ThirdParty/osmium/io/compression.hpp @@ -0,0 +1,240 @@ +#ifndef OSMIUM_IO_COMPRESSION_HPP +#define OSMIUM_IO_COMPRESSION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#else +#include +#endif +#include + +#include +#include +#include + +namespace osmium { + + namespace io { + + class Compressor { + + public: + + Compressor() = default; + + virtual ~Compressor() { + } + + virtual void write(const std::string& data) = 0; + + virtual void close() = 0; + + }; // class Compressor + + class Decompressor { + + public: + + static constexpr size_t input_buffer_size = 256 * 1024; + + Decompressor() = default; + + Decompressor(const Decompressor&) = delete; + Decompressor& operator=(const Decompressor&) = delete; + + Decompressor(Decompressor&&) = delete; + Decompressor& operator=(Decompressor&&) = delete; + + virtual ~Decompressor() { + } + + virtual std::string read() = 0; + + virtual void close() = 0; + + }; // class Decompressor + + /** + * This singleton factory class is used to register compression + * algorithms used for reading and writing OSM files. + * + * For each algorithm we store two functions that construct + * a compressor and decompressor object, respectively. + */ + class CompressionFactory { + + public: + + typedef std::function create_compressor_type; + typedef std::function create_decompressor_type; + + private: + + typedef std::map> compression_map_type; + + compression_map_type m_callbacks; + + CompressionFactory() = default; + + CompressionFactory(const CompressionFactory&) = delete; + CompressionFactory& operator=(const CompressionFactory&) = delete; + + CompressionFactory(CompressionFactory&&) = delete; + CompressionFactory& operator=(CompressionFactory&&) = delete; + + OSMIUM_NORETURN void error(osmium::io::file_compression compression) { + std::string error_message {"Support for compression '"}; + error_message += as_string(compression); + error_message += "' not compiled into this binary."; + throw std::runtime_error(error_message); + } + + public: + + static CompressionFactory& instance() { + static CompressionFactory factory; + return factory; + } + + bool register_compression(osmium::io::file_compression compression, create_compressor_type create_compressor, create_decompressor_type create_decompressor) { + compression_map_type::value_type cc(compression, std::make_pair(create_compressor, create_decompressor)); + return m_callbacks.insert(cc).second; + } + + std::unique_ptr create_compressor(osmium::io::file_compression compression, int fd) { + auto it = m_callbacks.find(compression); + + if (it != m_callbacks.end()) { + return std::unique_ptr((it->second.first)(fd)); + } + + error(compression); + } + + std::unique_ptr create_decompressor(osmium::io::file_compression compression, int fd) { + auto it = m_callbacks.find(compression); + + if (it != m_callbacks.end()) { + return std::unique_ptr((it->second.second)(fd)); + } + + error(compression); + } + + }; // class CompressionFactory + + class NoCompressor : public Compressor { + + int m_fd; + + public: + + NoCompressor(int fd) : + Compressor(), + m_fd(fd) { + } + + ~NoCompressor() override final { + this->close(); + } + + void write(const std::string& data) override final { + osmium::io::detail::reliable_write(m_fd, data.data(), data.size()); + } + + void close() override final { + if (m_fd >= 0) { + ::close(m_fd); + m_fd = -1; + } + } + + }; // class NoCompressor + + class NoDecompressor : public Decompressor { + + int m_fd; + + public: + + NoDecompressor(int fd) : + Decompressor(), + m_fd(fd) { + } + + ~NoDecompressor() override final { + this->close(); + } + + std::string read() override final { + std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0'); + ssize_t nread = ::read(m_fd, const_cast(buffer.data()), buffer.size()); + if (nread < 0) { + throw std::system_error(errno, std::system_category(), "Read failed"); + } + buffer.resize(static_cast(nread)); + return buffer; + } + + void close() override final { + if (m_fd >= 0) { + ::close(m_fd); + m_fd = -1; + } + } + + }; // class NoDecompressor + + namespace { + + const bool registered_no_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::none, + [](int fd) { return new osmium::io::NoCompressor(fd); }, + [](int fd) { return new osmium::io::NoDecompressor(fd); } + ); + + } // anonymous namespace + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_COMPRESSION_HPP diff --git a/ThirdParty/osmium/io/detail/input_format.hpp b/ThirdParty/osmium/io/detail/input_format.hpp new file mode 100644 index 000000000..13e5ca7d7 --- /dev/null +++ b/ThirdParty/osmium/io/detail/input_format.hpp @@ -0,0 +1,160 @@ +#ifndef OSMIUM_IO_DETAIL_INPUT_FORMAT_HPP +#define OSMIUM_IO_DETAIL_INPUT_FORMAT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace osmium { + + namespace thread { + template class Queue; + } // namespace thread + + namespace io { + + namespace detail { + + /** + * Virtual base class for all classes reading OSM files in different + * formats. + * + * Do not use this class or derived classes directly. Use the + * osmium::io::Reader class instead. + */ + class InputFormat { + + protected: + + osmium::io::File m_file; + osmium::osm_entity_bits::type m_read_which_entities; + osmium::thread::Queue& m_input_queue; + osmium::io::Header m_header; + + explicit InputFormat(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) : + m_file(file), + m_read_which_entities(read_which_entities), + m_input_queue(input_queue) { + m_header.has_multiple_object_versions(m_file.has_multiple_object_versions()); + } + + InputFormat(const InputFormat&) = delete; + InputFormat(InputFormat&&) = delete; + + InputFormat& operator=(const InputFormat&) = delete; + InputFormat& operator=(InputFormat&&) = delete; + + public: + + virtual ~InputFormat() { + } + + virtual osmium::memory::Buffer read() = 0; + + virtual void close() { + } + + virtual osmium::io::Header header() { + return m_header; + } + + }; // class InputFormat + + /** + * This factory class is used to create objects that read OSM data + * written in a specified format. + * + * Do not use this class directly. Instead use the osmium::io::Reader + * class. + */ + class InputFormatFactory { + + public: + + typedef std::function&)> create_input_type; + + private: + + typedef std::map map_type; + + map_type m_callbacks; + + InputFormatFactory() : + m_callbacks() { + } + + public: + + static InputFormatFactory& instance() { + static InputFormatFactory factory; + return factory; + } + + bool register_input_format(osmium::io::file_format format, create_input_type create_function) { + if (! m_callbacks.insert(map_type::value_type(format, create_function)).second) { + return false; + } + return true; + } + + std::unique_ptr create_input(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) { + file.check(); + + auto it = m_callbacks.find(file.format()); + if (it != m_callbacks.end()) { + return std::unique_ptr((it->second)(file, read_which_entities, input_queue)); + } + + throw std::runtime_error(std::string("Support for input format '") + as_string(file.format()) + "' not compiled into this binary."); + } + + }; // class InputFormatFactory + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_INPUT_FORMAT_HPP diff --git a/ThirdParty/osmium/io/detail/opl_output_format.hpp b/ThirdParty/osmium/io/detail/opl_output_format.hpp new file mode 100644 index 000000000..e96d7345c --- /dev/null +++ b/ThirdParty/osmium/io/detail/opl_output_format.hpp @@ -0,0 +1,303 @@ +#ifndef OSMIUM_IO_DETAIL_OPL_OUTPUT_FORMAT_HPP +#define OSMIUM_IO_DETAIL_OPL_OUTPUT_FORMAT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if BOOST_VERSION >= 104800 +# include +#else +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace io { + + class File; + + namespace detail { + + /** + * Writes out one buffer with OSM data in OPL format. + */ + class OPLOutputBlock : public osmium::handler::Handler { + + static constexpr size_t tmp_buffer_size = 100; + + osmium::memory::Buffer m_input_buffer; + + std::string m_out; + + char m_tmp_buffer[tmp_buffer_size+1]; + + template + void output_formatted(const char* format, TArgs&&... args) { +#ifndef _MSC_VER + int len = snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward(args)...); +#else + int len = _snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward(args)...); +#endif + assert(len > 0 && static_cast(len) < tmp_buffer_size); + m_out += m_tmp_buffer; + } + + void append_encoded_string(const std::string& data) { + boost::u8_to_u32_iterator it(data.cbegin(), data.cbegin(), data.cend()); + boost::u8_to_u32_iterator end(data.cend(), data.cend(), data.cend()); + boost::utf8_output_iterator> oit(std::back_inserter(m_out)); + + for (; it != end; ++it) { + uint32_t c = *it; + + // This is a list of Unicode code points that we let + // through instead of escaping them. It is incomplete + // and can be extended later. + // Generally we don't want to let through any character + // that has special meaning in the OPL format such as + // space, comma, @, etc. and any non-printing characters. + if ((0x0021 <= c && c <= 0x0024) || + (0x0026 <= c && c <= 0x002b) || + (0x002d <= c && c <= 0x003c) || + (0x003e <= c && c <= 0x003f) || + (0x0041 <= c && c <= 0x007e) || + (0x00a1 <= c && c <= 0x00ac) || + (0x00ae <= c && c <= 0x05ff)) { + *oit = c; + } else { + m_out += '%'; + output_formatted("%04x", c); + } + } + } + + void write_meta(const osmium::OSMObject& object) { + output_formatted("%" PRId64 " v%d d", object.id(), object.version()); + m_out += (object.visible() ? 'V' : 'D'); + output_formatted(" c%d t", object.changeset()); + m_out += object.timestamp().to_iso(); + output_formatted(" i%d u", object.uid()); + append_encoded_string(object.user()); + m_out += " T"; + bool first = true; + for (const auto& tag : object.tags()) { + if (first) { + first = false; + } else { + m_out += ','; + } + append_encoded_string(tag.key()); + m_out += '='; + append_encoded_string(tag.value()); + } + } + + void write_location(const osmium::Location location, const char x, const char y) { + if (location) { + output_formatted(" %c%.7f %c%.7f", x, location.lon_without_check(), y, location.lat_without_check()); + } else { + m_out += ' '; + m_out += x; + m_out += ' '; + m_out += y; + } + } + + public: + + explicit OPLOutputBlock(osmium::memory::Buffer&& buffer) : + m_input_buffer(std::move(buffer)), + m_out(), + m_tmp_buffer() { + } + + OPLOutputBlock(const OPLOutputBlock&) = delete; + OPLOutputBlock& operator=(const OPLOutputBlock&) = delete; + + OPLOutputBlock(OPLOutputBlock&& other) = default; + OPLOutputBlock& operator=(OPLOutputBlock&& other) = default; + + std::string operator()() { + osmium::apply(m_input_buffer.cbegin(), m_input_buffer.cend(), *this); + + std::string out; + std::swap(out, m_out); + return out; + } + + void node(const osmium::Node& node) { + m_out += 'n'; + write_meta(node); + write_location(node.location(), 'x', 'y'); + m_out += '\n'; + } + + void way(const osmium::Way& way) { + m_out += 'w'; + write_meta(way); + + m_out += " N"; + bool first = true; + for (const auto& node_ref : way.nodes()) { + if (first) { + first = false; + } else { + m_out += ','; + } + output_formatted("n%" PRId64, node_ref.ref()); + } + m_out += '\n'; + } + + void relation(const osmium::Relation& relation) { + m_out += 'r'; + write_meta(relation); + + m_out += " M"; + bool first = true; + for (const auto& member : relation.members()) { + if (first) { + first = false; + } else { + m_out += ','; + } + m_out += item_type_to_char(member.type()); + output_formatted("%" PRId64 "@", member.ref()); + m_out += member.role(); + } + m_out += '\n'; + } + + void changeset(const osmium::Changeset& changeset) { + output_formatted("c%d k%d s", changeset.id(), changeset.num_changes()); + m_out += changeset.created_at().to_iso(); + m_out += " e"; + m_out += changeset.closed_at().to_iso(); + output_formatted(" i%d u", changeset.uid()); + append_encoded_string(changeset.user()); + write_location(changeset.bounds().bottom_left(), 'x', 'y'); + write_location(changeset.bounds().top_right(), 'X', 'Y'); + m_out += " T"; + bool first = true; + for (const auto& tag : changeset.tags()) { + if (first) { + first = false; + } else { + m_out += ','; + } + append_encoded_string(tag.key()); + m_out += '='; + append_encoded_string(tag.value()); + } + + m_out += '\n'; + } + + }; // OPLOutputBlock + + class OPLOutputFormat : public osmium::io::detail::OutputFormat { + + OPLOutputFormat(const OPLOutputFormat&) = delete; + OPLOutputFormat& operator=(const OPLOutputFormat&) = delete; + + public: + + OPLOutputFormat(const osmium::io::File& file, data_queue_type& output_queue) : + OutputFormat(file, output_queue) { + } + + void write_buffer(osmium::memory::Buffer&& buffer) override final { + OPLOutputBlock output_block(std::move(buffer)); + m_output_queue.push(osmium::thread::Pool::instance().submit(std::move(output_block))); + while (m_output_queue.size() > 10) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // XXX + } + } + + void close() override final { + std::string out; + std::promise promise; + m_output_queue.push(promise.get_future()); + promise.set_value(out); + } + + }; // class OPLOutputFormat + + namespace { + + const bool registered_opl_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::opl, + [](const osmium::io::File& file, data_queue_type& output_queue) { + return new osmium::io::detail::OPLOutputFormat(file, output_queue); + }); + + } // anonymous namespace + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_OPL_OUTPUT_FORMAT_HPP diff --git a/ThirdParty/osmium/io/detail/output_format.hpp b/ThirdParty/osmium/io/detail/output_format.hpp new file mode 100644 index 000000000..6ce28fbee --- /dev/null +++ b/ThirdParty/osmium/io/detail/output_format.hpp @@ -0,0 +1,156 @@ +#ifndef OSMIUM_IO_DETAIL_OUTPUT_FORMAT_HPP +#define OSMIUM_IO_DETAIL_OUTPUT_FORMAT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace osmium { + + namespace memory { + class Buffer; + } + + namespace io { + + namespace detail { + + typedef osmium::thread::Queue> data_queue_type; + + /** + * Virtual base class for all classes writing OSM files in different + * formats. + * + * Do not use this class or derived classes directly. Use the + * osmium::io::Writer class instead. + */ + class OutputFormat { + + protected: + + osmium::io::File m_file; + data_queue_type& m_output_queue; + + public: + + explicit OutputFormat(const osmium::io::File& file, data_queue_type& output_queue) : + m_file(file), + m_output_queue(output_queue) { + } + + OutputFormat(const OutputFormat&) = delete; + OutputFormat(OutputFormat&&) = delete; + + OutputFormat& operator=(const OutputFormat&) = delete; + OutputFormat& operator=(OutputFormat&&) = delete; + + virtual ~OutputFormat() { + } + + virtual void write_header(const osmium::io::Header&) { + } + + virtual void write_buffer(osmium::memory::Buffer&&) = 0; + + virtual void close() = 0; + + }; // class OutputFormat + + /** + * This factory class is used to create objects that write OSM data + * into a specified output format. + * + * Do not use this class directly. Instead use the osmium::io::Writer + * class. + */ + class OutputFormatFactory { + + public: + + typedef std::function create_output_type; + + private: + + typedef std::map map_type; + + map_type m_callbacks; + + OutputFormatFactory() : + m_callbacks() { + } + + public: + + static OutputFormatFactory& instance() { + static OutputFormatFactory factory; + return factory; + } + + bool register_output_format(osmium::io::file_format format, create_output_type create_function) { + if (! m_callbacks.insert(map_type::value_type(format, create_function)).second) { + return false; + } + return true; + } + + std::unique_ptr create_output(const osmium::io::File& file, data_queue_type& output_queue) { + file.check(); + + auto it = m_callbacks.find(file.format()); + if (it != m_callbacks.end()) { + return std::unique_ptr((it->second)(file, output_queue)); + } + + throw std::runtime_error(std::string("Support for output format '") + as_string(file.format()) + "' not compiled into this binary."); + } + + }; // class OutputFormatFactory + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_OUTPUT_FORMAT_HPP diff --git a/ThirdParty/osmium/io/detail/pbf.hpp b/ThirdParty/osmium/io/detail/pbf.hpp new file mode 100644 index 000000000..cb44bb039 --- /dev/null +++ b/ThirdParty/osmium/io/detail/pbf.hpp @@ -0,0 +1,79 @@ +#ifndef OSMIUM_IO_DETAIL_PBF_HPP +#define OSMIUM_IO_DETAIL_PBF_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#define OSMIUM_LINK_WITH_LIBS_PBF -pthread -lz -lprotobuf-lite -losmpbf + +#include + +#include + +// needed for htonl and ntohl +#ifndef WIN32 +# include +#else +# include +#endif + +#include + +namespace osmium { + + inline item_type osmpbf_membertype_to_item_type(const OSMPBF::Relation::MemberType mt) { + switch (mt) { + case OSMPBF::Relation::NODE: + return item_type::node; + case OSMPBF::Relation::WAY: + return item_type::way; + case OSMPBF::Relation::RELATION: + return item_type::relation; + } + } + + inline OSMPBF::Relation::MemberType item_type_to_osmpbf_membertype(const item_type type) { + switch (type) { + case item_type::node: + return OSMPBF::Relation::NODE; + case item_type::way: + return OSMPBF::Relation::WAY; + case item_type::relation: + return OSMPBF::Relation::RELATION; + default: + throw std::runtime_error("Unknown relation member type"); + } + } + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_PBF_HPP diff --git a/ThirdParty/osmium/io/detail/pbf_input_format.hpp b/ThirdParty/osmium/io/detail/pbf_input_format.hpp new file mode 100644 index 000000000..36430bea5 --- /dev/null +++ b/ThirdParty/osmium/io/detail/pbf_input_format.hpp @@ -0,0 +1,681 @@ +#ifndef OSMIUM_IO_DETAIL_PBF_INPUT_FORMAT_HPP +#define OSMIUM_IO_DETAIL_PBF_INPUT_FORMAT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include // IWYU pragma: export +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace io { + + class File; + + namespace detail { + + class PBFPrimitiveBlockParser { + + static constexpr size_t initial_buffer_size = 10 * 1024; + + const void* m_data; + const size_t m_size; + + const OSMPBF::StringTable* m_stringtable; + int64_t m_lon_offset; + int64_t m_lat_offset; + int64_t m_date_factor; + int32_t m_granularity; + + osmium::osm_entity_bits::type m_read_types; + + osmium::memory::Buffer m_buffer; + + PBFPrimitiveBlockParser(const PBFPrimitiveBlockParser&) = delete; + PBFPrimitiveBlockParser(PBFPrimitiveBlockParser&&) = delete; + + PBFPrimitiveBlockParser& operator=(const PBFPrimitiveBlockParser&) = delete; + PBFPrimitiveBlockParser& operator=(PBFPrimitiveBlockParser&&) = delete; + + public: + + explicit PBFPrimitiveBlockParser(const void* data, const size_t size, osmium::osm_entity_bits::type read_types) : + m_data(data), + m_size(size), + m_stringtable(nullptr), + m_lon_offset(0), + m_lat_offset(0), + m_date_factor(1000), + m_granularity(100), + m_read_types(read_types), + m_buffer(initial_buffer_size) { + } + + ~PBFPrimitiveBlockParser() = default; + + osmium::memory::Buffer operator()() { + OSMPBF::PrimitiveBlock pbf_primitive_block; + if (!pbf_primitive_block.ParseFromArray(m_data, m_size)) { + throw std::runtime_error("Failed to parse PrimitiveBlock."); + } + + m_stringtable = &pbf_primitive_block.stringtable(); + m_lon_offset = pbf_primitive_block.lon_offset(); + m_lat_offset = pbf_primitive_block.lat_offset(); + m_date_factor = pbf_primitive_block.date_granularity() / 1000; + m_granularity = pbf_primitive_block.granularity(); + + for (int i=0; i < pbf_primitive_block.primitivegroup_size(); ++i) { + const OSMPBF::PrimitiveGroup& group = pbf_primitive_block.primitivegroup(i); + + if (group.has_dense()) { + if (m_read_types & osmium::osm_entity_bits::node) parse_dense_node_group(group); + } else if (group.ways_size() != 0) { + if (m_read_types & osmium::osm_entity_bits::way) parse_way_group(group); + } else if (group.relations_size() != 0) { + if (m_read_types & osmium::osm_entity_bits::relation) parse_relation_group(group); + } else if (group.nodes_size() != 0) { + if (m_read_types & osmium::osm_entity_bits::node) parse_node_group(group); + } else { + throw std::runtime_error("Group of unknown type."); + } + } + + return std::move(m_buffer); + } + + private: + + template + void parse_attributes(TBuilder& builder, const TPBFObject& pbf_object) { + auto& object = builder.object(); + + object.id(pbf_object.id()); + + if (pbf_object.has_info()) { + object.version(pbf_object.info().version()) + .changeset(pbf_object.info().changeset()) + .timestamp(pbf_object.info().timestamp() * m_date_factor) + .uid_from_signed(pbf_object.info().uid()); + if (pbf_object.info().has_visible()) { + object.visible(pbf_object.info().visible()); + } + builder.add_user(m_stringtable->s(pbf_object.info().user_sid()).data()); + } else { + builder.add_user(""); + } + } + + void parse_node_group(const OSMPBF::PrimitiveGroup& group) { + for (int i=0; i < group.nodes_size(); ++i) { + osmium::builder::NodeBuilder builder(m_buffer); + const OSMPBF::Node& pbf_node = group.nodes(i); + parse_attributes(builder, pbf_node); + + if (builder.object().visible()) { + builder.object().location(osmium::Location( + (pbf_node.lon() * m_granularity + m_lon_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision), + (pbf_node.lat() * m_granularity + m_lat_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision))); + } + + if (pbf_node.keys_size() > 0) { + osmium::builder::TagListBuilder tl_builder(m_buffer, &builder); + for (int tag=0; tag < pbf_node.keys_size(); ++tag) { + tl_builder.add_tag(m_stringtable->s(static_cast(pbf_node.keys(tag))).data(), + m_stringtable->s(static_cast(pbf_node.vals(tag))).data()); + } + } + + m_buffer.commit(); + } + } + + void parse_way_group(const OSMPBF::PrimitiveGroup& group) { + for (int i=0; i < group.ways_size(); ++i) { + osmium::builder::WayBuilder builder(m_buffer); + const OSMPBF::Way& pbf_way = group.ways(i); + parse_attributes(builder, pbf_way); + + if (pbf_way.refs_size() > 0) { + osmium::builder::WayNodeListBuilder wnl_builder(m_buffer, &builder); + int64_t ref = 0; + for (int n=0; n < pbf_way.refs_size(); ++n) { + ref += pbf_way.refs(n); + wnl_builder.add_node_ref(ref); + } + } + + if (pbf_way.keys_size() > 0) { + osmium::builder::TagListBuilder tl_builder(m_buffer, &builder); + for (int tag=0; tag < pbf_way.keys_size(); ++tag) { + tl_builder.add_tag(m_stringtable->s(static_cast(pbf_way.keys(tag))).data(), + m_stringtable->s(static_cast(pbf_way.vals(tag))).data()); + } + } + + m_buffer.commit(); + } + } + + void parse_relation_group(const OSMPBF::PrimitiveGroup& group) { + for (int i=0; i < group.relations_size(); ++i) { + osmium::builder::RelationBuilder builder(m_buffer); + const OSMPBF::Relation& pbf_relation = group.relations(i); + parse_attributes(builder, pbf_relation); + + if (pbf_relation.types_size() > 0) { + osmium::builder::RelationMemberListBuilder rml_builder(m_buffer, &builder); + int64_t ref = 0; + for (int n=0; n < pbf_relation.types_size(); ++n) { + ref += pbf_relation.memids(n); + rml_builder.add_member(osmpbf_membertype_to_item_type(pbf_relation.types(n)), ref, m_stringtable->s(pbf_relation.roles_sid(n)).data()); + } + } + + if (pbf_relation.keys_size() > 0) { + osmium::builder::TagListBuilder tl_builder(m_buffer, &builder); + for (int tag=0; tag < pbf_relation.keys_size(); ++tag) { + tl_builder.add_tag(m_stringtable->s(static_cast(pbf_relation.keys(tag))).data(), + m_stringtable->s(static_cast(pbf_relation.vals(tag))).data()); + } + } + + m_buffer.commit(); + } + } + + int add_tags(const OSMPBF::DenseNodes& dense, int n, osmium::builder::NodeBuilder* builder) { + if (n >= dense.keys_vals_size()) { + return n; + } + + if (dense.keys_vals(n) == 0) { + return n+1; + } + + osmium::builder::TagListBuilder tl_builder(m_buffer, builder); + + while (n < dense.keys_vals_size()) { + int tag_key_pos = dense.keys_vals(n++); + + if (tag_key_pos == 0) { + break; + } + + tl_builder.add_tag(m_stringtable->s(tag_key_pos).data(), + m_stringtable->s(dense.keys_vals(n)).data()); + + ++n; + } + + return n; + } + + void parse_dense_node_group(const OSMPBF::PrimitiveGroup& group) { + int64_t last_dense_id = 0; + int64_t last_dense_latitude = 0; + int64_t last_dense_longitude = 0; + int64_t last_dense_uid = 0; + int64_t last_dense_user_sid = 0; + int64_t last_dense_changeset = 0; + int64_t last_dense_timestamp = 0; + int last_dense_tag = 0; + + const OSMPBF::DenseNodes& dense = group.dense(); + + for (int i=0; i < dense.id_size(); ++i) { + bool visible = true; + + last_dense_id += dense.id(i); + last_dense_latitude += dense.lat(i); + last_dense_longitude += dense.lon(i); + + if (dense.has_denseinfo()) { + last_dense_changeset += dense.denseinfo().changeset(i); + last_dense_timestamp += dense.denseinfo().timestamp(i); + last_dense_uid += dense.denseinfo().uid(i); + last_dense_user_sid += dense.denseinfo().user_sid(i); + if (dense.denseinfo().visible_size() > 0) { + visible = dense.denseinfo().visible(i); + } + assert(last_dense_changeset >= 0); + assert(last_dense_timestamp >= 0); + assert(last_dense_uid >= -1); + assert(last_dense_user_sid >= 0); + } + + osmium::builder::NodeBuilder builder(m_buffer); + osmium::Node& node = builder.object(); + + node.id(last_dense_id); + + if (dense.has_denseinfo()) { + auto v = dense.denseinfo().version(i); + assert(v > 0); + node.version(static_cast(v)); + node.changeset(last_dense_changeset); + node.timestamp(last_dense_timestamp * m_date_factor); + node.uid_from_signed(last_dense_uid); + node.visible(visible); + builder.add_user(m_stringtable->s(last_dense_user_sid).data()); + } else { + builder.add_user(""); + } + + if (visible) { + builder.object().location(osmium::Location( + (last_dense_longitude * m_granularity + m_lon_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision), + (last_dense_latitude * m_granularity + m_lat_offset) / (OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision))); + } + + last_dense_tag = add_tags(dense, last_dense_tag, &builder); + m_buffer.commit(); + } + } + + }; // class PBFPrimitiveBlockParser + + typedef osmium::thread::Queue> queue_type; + + class InputQueueReader { + + osmium::thread::Queue& m_queue; + std::string m_buffer; + + public: + + InputQueueReader(osmium::thread::Queue& queue) : + m_queue(queue) { + } + + bool operator()(unsigned char* data, size_t size) { + while (m_buffer.size() < size) { + std::string new_data; + m_queue.wait_and_pop(new_data); + if (new_data.empty()) { + return false; + } + m_buffer += new_data; + } + memcpy(data, m_buffer.data(), size); + m_buffer.erase(0, size); + return true; + } + + }; + + template + class BlobParser { + + protected: + + std::shared_ptr m_input_buffer; + const int m_size; + const int m_blob_num; + InputQueueReader& m_input_queue_reader; + + BlobParser(const int size, const int blob_num, InputQueueReader& input_queue_reader) : + m_input_buffer(new unsigned char[size], [](unsigned char* ptr) { delete[] ptr; }), + m_size(size), + m_blob_num(blob_num), + m_input_queue_reader(input_queue_reader) { + if (size < 0 || size > OSMPBF::max_uncompressed_blob_size) { + std::ostringstream errmsg; + errmsg << "invalid blob size: " << size; + throw std::runtime_error(errmsg.str()); + } + if (! input_queue_reader(m_input_buffer.get(), size)) { + // EOF + throw std::runtime_error("read error (EOF)"); + } + } + + public: + + void doit() { + OSMPBF::Blob pbf_blob; + if (!pbf_blob.ParseFromArray(m_input_buffer.get(), m_size)) { + throw std::runtime_error("failed to parse blob"); + } + + if (pbf_blob.has_raw()) { + static_cast(this)->handle_blob(pbf_blob.raw()); + return; + } else if (pbf_blob.has_zlib_data()) { + auto raw_size = pbf_blob.raw_size(); + assert(raw_size >= 0); + assert(raw_size <= OSMPBF::max_uncompressed_blob_size); + + std::string unpack_buffer { osmium::io::detail::zlib_uncompress(pbf_blob.zlib_data(), static_cast(raw_size)) }; + static_cast(this)->handle_blob(unpack_buffer); + return; + } else if (pbf_blob.has_lzma_data()) { + throw std::runtime_error("lzma blobs not implemented"); + } else { + throw std::runtime_error("Blob contains no data"); + } + } + + osmium::memory::Buffer operator()() { + OSMPBF::Blob pbf_blob; + if (!pbf_blob.ParseFromArray(m_input_buffer.get(), m_size)) { + throw std::runtime_error("failed to parse blob"); + } + + if (pbf_blob.has_raw()) { + return static_cast(this)->handle_blob(pbf_blob.raw()); + } else if (pbf_blob.has_zlib_data()) { + auto raw_size = pbf_blob.raw_size(); + assert(raw_size >= 0); + assert(raw_size <= OSMPBF::max_uncompressed_blob_size); + + std::string unpack_buffer { osmium::io::detail::zlib_uncompress(pbf_blob.zlib_data(), static_cast(raw_size)) }; + return static_cast(this)->handle_blob(unpack_buffer); + } else if (pbf_blob.has_lzma_data()) { + throw std::runtime_error("lzma blobs not implemented"); + } else { + throw std::runtime_error("Blob contains no data"); + } + } + + }; // class BlobParser; + + class HeaderBlobParser : public BlobParser { + + osmium::io::Header& m_header; + + void handle_blob(const std::string& data) { + OSMPBF::HeaderBlock pbf_header_block; + if (!pbf_header_block.ParseFromArray(data.data(), data.size())) { + throw std::runtime_error("Failed to parse HeaderBlock."); + } + + for (int i=0; i < pbf_header_block.required_features_size(); ++i) { + const std::string& feature = pbf_header_block.required_features(i); + + if (feature == "OsmSchema-V0.6") continue; + if (feature == "DenseNodes") { + m_header.set("pbf_dense_nodes", true); + continue; + } + if (feature == "HistoricalInformation") { + m_header.has_multiple_object_versions(true); + continue; + } + + std::ostringstream errmsg; + errmsg << "Required feature not supported: " << feature; + throw std::runtime_error(errmsg.str()); + } + + if (pbf_header_block.has_writingprogram()) { + m_header.set("generator", pbf_header_block.writingprogram()); + } + + if (pbf_header_block.has_bbox()) { + const OSMPBF::HeaderBBox& pbf_bbox = pbf_header_block.bbox(); + const int64_t resolution_convert = OSMPBF::lonlat_resolution / osmium::Location::coordinate_precision; + osmium::Box box; + box.extend(osmium::Location(pbf_bbox.left() / resolution_convert, pbf_bbox.bottom() / resolution_convert)); + box.extend(osmium::Location(pbf_bbox.right() / resolution_convert, pbf_bbox.top() / resolution_convert)); + m_header.add_box(box); + } + + if (pbf_header_block.has_osmosis_replication_timestamp()) { + m_header.set("osmosis_replication_timestamp", osmium::Timestamp(pbf_header_block.osmosis_replication_timestamp()).to_iso()); + } + + if (pbf_header_block.has_osmosis_replication_sequence_number()) { + m_header.set("osmosis_replication_sequence_number", std::to_string(pbf_header_block.osmosis_replication_sequence_number())); + } + + if (pbf_header_block.has_osmosis_replication_base_url()) { + m_header.set("osmosis_replication_base_url", pbf_header_block.osmosis_replication_base_url()); + } + } + + public: + + friend class BlobParser; + + HeaderBlobParser(const int size, InputQueueReader& input_queue_reader, osmium::io::Header& header) : + BlobParser(size, 0, input_queue_reader), + m_header(header) { + } + + }; // class HeaderBlobParser + + class DataBlobParser : public BlobParser { + + osmium::osm_entity_bits::type m_read_types; + + osmium::memory::Buffer handle_blob(const std::string& data) { + PBFPrimitiveBlockParser parser(data.data(), data.size(), m_read_types); + return std::move(parser()); + } + + public: + + friend class BlobParser; + + DataBlobParser(const int size, const int blob_num, InputQueueReader& input_queue_reader, osmium::osm_entity_bits::type read_types) : + BlobParser(size, blob_num, input_queue_reader), + m_read_types(read_types) { + } + + }; // class DataBlobParser + + /** + * Class for parsing PBF files. + */ + class PBFInputFormat : public osmium::io::detail::InputFormat { + + bool m_use_thread_pool; + queue_type m_queue; + const size_t m_max_work_queue_size; + const size_t m_max_buffer_queue_size; + std::atomic m_done; + std::thread m_reader; + OSMPBF::BlobHeader m_blob_header; + InputQueueReader m_input_queue_reader; + + /** + * Read BlobHeader by first reading the size and then the BlobHeader. + * The BlobHeader contains a type field (which is checked against + * the expected type) and a size field. + * + * @param expected_type Expected type of data ("OSMHeader" or "OSMData"). + * @return Size of the data read from BlobHeader (0 on EOF). + */ + size_t read_blob_header(const char* expected_type) { + uint32_t size_in_network_byte_order; + + if (! m_input_queue_reader(reinterpret_cast(&size_in_network_byte_order), sizeof(size_in_network_byte_order))) { + return 0; // EOF + } + + uint32_t size = ntohl(size_in_network_byte_order); + if (size > static_cast(OSMPBF::max_blob_header_size)) { + throw std::runtime_error("Invalid BlobHeader size"); + } + + unsigned char blob_header_buffer[OSMPBF::max_blob_header_size]; + if (! m_input_queue_reader(blob_header_buffer, size)) { + throw std::runtime_error("Read error."); + } + + if (!m_blob_header.ParseFromArray(blob_header_buffer, static_cast(size))) { + throw std::runtime_error("Failed to parse BlobHeader."); + } + + if (std::strcmp(m_blob_header.type().c_str(), expected_type)) { + throw std::runtime_error("Blob does not have expected type (OSMHeader in first Blob, OSMData in following Blobs)."); + } + + return static_cast(m_blob_header.datasize()); + } + + void parse_osm_data(osmium::osm_entity_bits::type read_types) { + osmium::thread::set_thread_name("_osmium_pbf_in"); + int n=0; + while (size_t size = read_blob_header("OSMData")) { + DataBlobParser data_blob_parser(size, n, m_input_queue_reader, read_types); + + if (m_use_thread_pool) { + m_queue.push(osmium::thread::Pool::instance().submit(data_blob_parser)); + + // if the work queue is getting too large, wait for a while + while (!m_done && osmium::thread::Pool::instance().queue_size() >= m_max_work_queue_size) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } else { + std::promise promise; + m_queue.push(promise.get_future()); + promise.set_value(data_blob_parser()); + } + ++n; + + // wait if the backlog of buffers with parsed data is too large + while (!m_done && m_queue.size() > m_max_buffer_queue_size) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + + if (m_done) { + return; + } + } + m_done = true; + } + + public: + + /** + * Instantiate PBF Parser + * + * @param file osmium::io::File instance describing file to be read from. + * @param read_which_entities Which types of OSM entities (nodes, ways, relations, changesets) should be parsed? + * @param input_queue String queue where data is read from. + */ + PBFInputFormat(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) : + osmium::io::detail::InputFormat(file, read_which_entities, input_queue), + m_use_thread_pool(true), + m_queue(), + m_max_work_queue_size(10), // XXX tune these settings + m_max_buffer_queue_size(20), // XXX tune these settings + m_done(false), + m_input_queue_reader(input_queue) { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + // handle OSMHeader + size_t size = read_blob_header("OSMHeader"); + + { + HeaderBlobParser header_blob_parser(size, m_input_queue_reader, m_header); + header_blob_parser.doit(); + } + + if (m_read_which_entities != osmium::osm_entity_bits::nothing) { + m_reader = std::thread(&PBFInputFormat::parse_osm_data, this, m_read_which_entities); + } + } + + ~PBFInputFormat() { + m_done = true; + if (m_reader.joinable()) { + m_reader.join(); + } + } + + /** + * Returns the next buffer with OSM data read from the PBF file. + * Blocks if data is not available yet. + * Returns an empty buffer at end of input. + */ + osmium::memory::Buffer read() override { + if (!m_done || !m_queue.empty()) { + std::future buffer_future; + m_queue.wait_and_pop(buffer_future); + return std::move(buffer_future.get()); + } + + return osmium::memory::Buffer(); + } + + }; // class PBFInputFormat + + namespace { + + const bool registered_pbf_input = osmium::io::detail::InputFormatFactory::instance().register_input_format(osmium::io::file_format::pbf, + [](const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) { + return new osmium::io::detail::PBFInputFormat(file, read_which_entities, input_queue); + }); + + } // anonymous namespace + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_PBF_INPUT_FORMAT_HPP diff --git a/ThirdParty/osmium/io/detail/pbf_output_format.hpp b/ThirdParty/osmium/io/detail/pbf_output_format.hpp new file mode 100644 index 000000000..d24062c20 --- /dev/null +++ b/ThirdParty/osmium/io/detail/pbf_output_format.hpp @@ -0,0 +1,950 @@ +#ifndef OSMIUM_IO_DETAIL_PBF_OUTPUT_FORMAT_HPP +#define OSMIUM_IO_DETAIL_PBF_OUTPUT_FORMAT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +/* + +About the .osm.pbf file format +This is an excerpt of + +The .osm.pbf format and it's derived formats (.osh.pbf and .osc.pbf) are encoded +using googles protobuf library for the low-level storage. They are constructed +by nesting data on two levels: + +On the lower level the file is constructed using BlobHeaders and Blobs. A .osm.pbf +file contains multiple sequences of + 1. a 4-byte header size, stored in network-byte-order + 2. a BlobHeader of exactly this size + 3. a Blob + +The BlobHeader tells the reader about the type and size of the following Blob. The +Blob can contain data in raw or zlib-compressed form. After uncompressing the blob +it is treated differently depending on the type specified in the BlobHeader. + +The contents of the Blob belongs to the higher level. It contains either an HeaderBlock +(type="OSMHeader") or an PrimitiveBlock (type="OSMData"). The file needs to have +at least one HeaderBlock before the first PrimitiveBlock. + +The HeaderBlock contains meta-information like the writing program or a bbox. It may +also contain multiple "required features" that describe what kinds of input a +reading program needs to handle in order to fully understand the files' contents. + +The PrimitiveBlock can store multiple types of objects (i.e. 5 nodes, 2 ways and +1 relation). It contains one or more PrimitiveGroup which in turn contain multiple +nodes, ways or relations. A PrimitiveGroup should only contain one kind of object. + +There's a special kind of "object type" called dense-nodes. It is used to store nodes +in a very dense format, avoiding message overheads and using delta-encoding for nearly +all ids. + +All Strings are stored as indexes to rows in a StringTable. The StringTable contains +one row for each used string, so strings that are used multiple times need to be +stored only once. The StringTable is sorted by usage-count, so the most often used +string is stored at index 1. + +A simple outline of a .osm.pbf file could look like this: + + 4-bytes header size + BlobHeader + Blob + HeaderBlock + 4-bytes header size + BlobHeader + Blob + PrimitiveBlock + StringTable + PrimitiveGroup + 5 nodes + PrimitiveGroup + 2 ways + PrimitiveGroup + 1 relation + +More complete outlines of real .osm.pbf files can be created using the osmpbf-outline tool: + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include // IWYU pragma: export +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace io { + + namespace detail { + + namespace { + + /** + * Serialize a protobuf message into a Blob, optionally apply compression + * and return it together with a BlobHeader ready to be written to a file. + * + * @param type Type-string used in the BlobHeader. + * @param msg Protobuf-message. + * @param use_compression Should the output be compressed using zlib? + */ + std::string serialize_blob(const std::string& type, const google::protobuf::MessageLite& msg, bool use_compression) { + OSMPBF::Blob pbf_blob; + + { + std::string content; + msg.SerializeToString(&content); + + pbf_blob.set_raw_size(content.size()); + + if (use_compression) { + pbf_blob.set_zlib_data(osmium::io::detail::zlib_compress(content)); + } else { + pbf_blob.set_raw(content); + } + } + + std::string blob_data; + pbf_blob.SerializeToString(&blob_data); + + OSMPBF::BlobHeader pbf_blob_header; + pbf_blob_header.set_type(type); + pbf_blob_header.set_datasize(blob_data.size()); + + std::string blob_header_data; + pbf_blob_header.SerializeToString(&blob_header_data); + + uint32_t sz = htonl(blob_header_data.size()); + + // write to output: the 4-byte BlobHeader-Size followed by the BlobHeader followed by the Blob + std::string output; + output.reserve(sizeof(sz) + blob_header_data.size() + blob_data.size()); + output.append(reinterpret_cast(&sz), sizeof(sz)); + output.append(blob_header_data); + output.append(blob_data); + + return output; + } + + } // anonymous namespace + + class PBFOutputFormat : public osmium::io::detail::OutputFormat, public osmium::handler::Handler { + + /** + * This class models a variable that keeps track of the value + * it was last set to and returns the delta between old and + * new value from the update() call. + */ + template + class Delta { + + T m_value; + + public: + + Delta() : + m_value(0) { + } + + void clear() { + m_value = 0; + } + + T update(T new_value) { + using std::swap; + swap(m_value, new_value); + return m_value - new_value; + } + + }; // class Delta + + /** + * Maximum number of items in a primitive block. + * + * The uncompressed length of a Blob *should* be less + * than 16 megabytes and *must* be less than 32 megabytes. + * + * A block may contain any number of entities, as long as + * the size limits for the surrounding blob are obeyed. + * However, for simplicity, the current Osmosis (0.38) + * as well as Osmium implementation always + * uses at most 8k entities in a block. + */ + static constexpr uint32_t max_block_contents = 8000; + + /** + * The output buffer (block) will be filled to about + * 95% and then written to disk. This leaves more than + * enough space for the string table (which typically + * needs about 0.1 to 0.3% of the block size). + */ + static constexpr int buffer_fill_percent = 95; + + /** + * protobuf-struct of a HeaderBlock + */ + OSMPBF::HeaderBlock pbf_header_block; + + /** + * protobuf-struct of a PrimitiveBlock + */ + OSMPBF::PrimitiveBlock pbf_primitive_block; + + /** + * pointer to PrimitiveGroups inside the current PrimitiveBlock, + * used for writing nodes, ways or relations + */ + OSMPBF::PrimitiveGroup* pbf_nodes; + OSMPBF::PrimitiveGroup* pbf_ways; + OSMPBF::PrimitiveGroup* pbf_relations; + + /** + * To flexibly handle multiple resolutions, the granularity, or + * resolution used for representing locations is adjustable in + * multiples of 1 nanodegree. The default scaling factor is 100 + * nanodegrees, corresponding to about ~1cm at the equator. + * This is the current resolution of the OSM database. + */ + int m_location_granularity; + + /** + * The granularity used for representing timestamps is also adjustable in + * multiples of 1 millisecond. The default scaling factor is 1000 + * milliseconds, which is the current resolution of the OSM database. + */ + int m_date_granularity; + + /** + * should nodes be serialized into the dense format? + * + * nodes can be encoded one of two ways, as a Node + * (m_use_dense_nodes = false) and a special dense format. + * In the dense format, all information is stored 'column wise', + * as an array of ID's, array of latitudes, and array of + * longitudes. Each column is delta-encoded. This reduces + * header overheads and allows delta-coding to work very effectively. + */ + bool m_use_dense_nodes {true}; + + /** + * should the PBF blobs contain zlib compressed data? + * + * the zlib compression is optional, it's possible to store the + * blobs in raw format. Disabling the compression can improve the + * writing speed a little but the output will be 2x to 3x bigger. + */ + bool m_use_compression {true}; + + /** + * While the .osm.pbf-format is able to carry all meta information, it is + * also able to omit this information to reduce size. + */ + bool m_should_add_metadata {true}; + + /** + * Should the visible flag be added on objects? + */ + bool m_add_visible; + + /** + * counter used to quickly check the number of objects stored inside + * the current PrimitiveBlock. When the counter reaches max_block_contents + * the PrimitiveBlock is serialized into a Blob and flushed to the file. + * + * this check is performed in check_block_contents_counter() which is + * called once for each object. + */ + uint16_t primitive_block_contents; + uint32_t primitive_block_size; + + // StringTable management + StringTable string_table; + + /** + * These variables are used to calculate the + * delta-encoding while storing dense-nodes. It holds the last seen values + * from which the difference is stored into the protobuf. + */ + Delta m_delta_id; + Delta m_delta_lat; + Delta m_delta_lon; + Delta m_delta_timestamp; + Delta m_delta_changeset; + Delta m_delta_uid; + Delta m_delta_user_sid; + + bool debug; + + bool has_debug_level(int) { + return false; + } + + ///// Blob writing ///// + + /** + * Before a PrimitiveBlock gets serialized, all interim StringTable-ids needs to be + * mapped to the associated real StringTable ids. This is done in this function. + * + * This function needs to know about the concrete structure of all item types to find + * all occurrences of string-ids. + */ + void map_string_ids() { + // test, if the node-block has been allocated + if (pbf_nodes) { + // iterate over all nodes, passing them to the map_common_string_ids function + for (int i=0, l=pbf_nodes->nodes_size(); imutable_nodes(i)); + } + + // test, if the node-block has a densenodes structure + if (pbf_nodes->has_dense()) { + // get a pointer to the densenodes structure + OSMPBF::DenseNodes* dense = pbf_nodes->mutable_dense(); + + // in the densenodes structure keys and vals are encoded in an intermixed + // array, individual nodes are seperated by a value of 0 (0 in the StringTable + // is always unused). String-ids of 0 are thus kept alone. + for (int i=0, l=dense->keys_vals_size(); i 0 to real string ids + auto sid = dense->keys_vals(i); + assert(sid >= 0); + assert(sid < std::numeric_limits::max()); + if (sid > 0) { + dense->set_keys_vals(i, string_table.map_string_id(static_cast(sid))); + } + } + + // test if the densenodes block has meta infos + if (dense->has_denseinfo()) { + // get a pointer to the denseinfo structure + OSMPBF::DenseInfo* denseinfo = dense->mutable_denseinfo(); + + // iterate over all username string-ids + for (int i=0, l=denseinfo->user_sid_size(); i 0 to real string ids + auto usid = denseinfo->user_sid(i); + assert(usid < std::numeric_limits::max()); + auto user_sid = string_table.map_string_id(static_cast(usid)); + + // delta encode the string-id + denseinfo->set_user_sid(i, m_delta_user_sid.update(user_sid)); + } + } + } + } + + // test, if the ways-block has been allocated + if (pbf_ways) { + // iterate over all ways, passing them to the map_common_string_ids function + for (int i=0, l=pbf_ways->ways_size(); imutable_ways(i)); + } + } + + // test, if the relations-block has been allocated + if (pbf_relations) { + // iterate over all relations + for (int i=0, l=pbf_relations->relations_size(); imutable_relations(i); + + // pass them to the map_common_string_ids function + map_common_string_ids(relation); + + // iterate over all relation members, mapping the interim string-ids + // of the role to real string ids + for (int mi=0, ml=relation->roles_sid_size(); miset_roles_sid(mi, string_table.map_string_id(relation->roles_sid(mi))); + } + } + } + } + + /** + * a helper function used in map_string_ids to map common interim string-ids of the + * user name and all tags to real string ids. + * + * TPBFObject is either OSMPBF::Node, OSMPBF::Way or OSMPBF::Relation. + */ + template + void map_common_string_ids(TPBFObject* in) { + // if the object has meta-info attached + if (in->has_info()) { + // map the interim-id of the user name to a real id + OSMPBF::Info* info = in->mutable_info(); + info->set_user_sid(string_table.map_string_id(info->user_sid())); + } + + // iterate over all tags and map the interim-ids of the key and the value to real ids + for (int i=0, l=in->keys_size(); iset_keys(i, string_table.map_string_id(in->keys(i))); + in->set_vals(i, string_table.map_string_id(in->vals(i))); + } + } + + + ///// MetaData helper ///// + + /** + * convert a double lat or lon value to an int, respecting the current blocks granularity + */ + int64_t lonlat2int(double lonlat) { + return round(lonlat * OSMPBF::lonlat_resolution / location_granularity()); + } + + /** + * convert a timestamp to an int, respecting the current blocks granularity + */ + int64_t timestamp2int(time_t timestamp) { + return round(timestamp * (static_cast(1000) / date_granularity())); + } + + /** + * helper function used in the write()-calls to apply common information from an osmium-object + * onto a pbf-object. + * + * TPBFObject is either OSMPBF::Node, OSMPBF::Way or OSMPBF::Relation. + */ + template + void apply_common_info(const osmium::OSMObject& in, TPBFObject* out) { + // set the object-id + out->set_id(in.id()); + + // iterate over all tags and set the keys and vals, recording the strings in the + // interim StringTable and storing the interim ids + for (const auto& tag : in.tags()) { + out->add_keys(string_table.record_string(tag.key())); + out->add_vals(string_table.record_string(tag.value())); + } + + if (m_should_add_metadata) { + // add an info-section to the pbf object and set the meta-info on it + OSMPBF::Info* out_info = out->mutable_info(); + if (m_add_visible) { + out_info->set_visible(in.visible()); + } + out_info->set_version(static_cast<::google::protobuf::int32>(in.version())); + out_info->set_timestamp(timestamp2int(in.timestamp())); + out_info->set_changeset(in.changeset()); + out_info->set_uid(static_cast<::google::protobuf::int32>(in.uid())); + out_info->set_user_sid(string_table.record_string(in.user())); + } + } + + + ///// High-Level Block writing ///// + + /** + * store the current pbf_header_block into a Blob and clear this struct afterwards. + */ + void store_header_block() { + if (debug && has_debug_level(1)) { + std::cerr << "storing header block" << std::endl; + } + + std::promise promise; + m_output_queue.push(promise.get_future()); + promise.set_value(serialize_blob("OSMHeader", pbf_header_block, m_use_compression)); + + pbf_header_block.Clear(); + } + + /** + * store the interim StringTable to the current pbf_primitive_block, map all interim string ids + * to real StringTable ids and then store the current pbf_primitive_block into a Blob and clear + * this struct and all related pointers and maps afterwards. + */ + void store_primitive_block() { + if (debug && has_debug_level(1)) { + std::cerr << "storing primitive block with " << primitive_block_contents << " items" << std::endl; + } + + // set the granularity + pbf_primitive_block.set_granularity(location_granularity()); + pbf_primitive_block.set_date_granularity(date_granularity()); + + // store the interim StringTable into the protobuf object + string_table.store_stringtable(pbf_primitive_block.mutable_stringtable()); + + // map all interim string ids to real ids + map_string_ids(); + + std::promise promise; + m_output_queue.push(promise.get_future()); + promise.set_value(serialize_blob("OSMData", pbf_primitive_block, m_use_compression)); + while (m_output_queue.size() > 10) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // XXX + } + + // clear the PrimitiveBlock struct + pbf_primitive_block.Clear(); + + // clear the interim StringTable and its id map + string_table.clear(); + + // reset the delta variables + m_delta_id.clear(); + m_delta_lat.clear(); + m_delta_lon.clear(); + m_delta_timestamp.clear(); + m_delta_changeset.clear(); + m_delta_uid.clear(); + m_delta_user_sid.clear(); + + // reset the contents-counter to zero + primitive_block_contents = 0; + primitive_block_size = 0; + + // reset the node/way/relation pointers to nullptr + pbf_nodes = nullptr; + pbf_ways = nullptr; + pbf_relations = nullptr; + } + + /** + * this little function checks primitive_block_contents counter against its maximum and calls + * store_primitive_block to flush the block to the disk when it's reached. It's also responsible + * for increasing this counter. + * + * this function also checks the estimated size of the current block and calls store_primitive_block + * when the estimated size reaches buffer_fill_percent of the maximum uncompressed blob size. + */ + void check_block_contents_counter() { + if (primitive_block_contents >= max_block_contents) { + store_primitive_block(); + } else if (primitive_block_size > (static_cast(OSMPBF::max_uncompressed_blob_size) * buffer_fill_percent / 100)) { + if (debug && has_debug_level(1)) { + std::cerr << "storing primitive_block with only " << primitive_block_contents << " items, because its ByteSize (" << primitive_block_size << ") reached " << + (static_cast(primitive_block_size) / static_cast(OSMPBF::max_uncompressed_blob_size) * 100.0) << "% of the maximum blob-size" << std::endl; + } + + store_primitive_block(); + } + + ++primitive_block_contents; + } + + + ///// Block content writing ///// + + /** + * Add a node to the block. + * + * @param node The node to add. + */ + void write_node(const osmium::Node& node) { + // add a way to the group + OSMPBF::Node* pbf_node = pbf_nodes->add_nodes(); + + // copy the common meta-info from the osmium-object to the pbf-object + apply_common_info(node, pbf_node); + + // modify lat & lon to integers, respecting the block's granularity and copy + // the ints to the pbf-object + pbf_node->set_lon(lonlat2int(node.location().lon_without_check())); + pbf_node->set_lat(lonlat2int(node.location().lat_without_check())); + } + + /** + * Add a node to the block using DenseNodes. + * + * @param node The node to add. + */ + void write_dense_node(const osmium::Node& node) { + // add a DenseNodes-Section to the PrimitiveGroup + OSMPBF::DenseNodes* dense = pbf_nodes->mutable_dense(); + + // copy the id, delta encoded + dense->add_id(m_delta_id.update(node.id())); + + // copy the longitude, delta encoded + dense->add_lon(m_delta_lon.update(lonlat2int(node.location().lon_without_check()))); + + // copy the latitude, delta encoded + dense->add_lat(m_delta_lat.update(lonlat2int(node.location().lat_without_check()))); + + // in the densenodes structure keys and vals are encoded in an intermixed + // array, individual nodes are seperated by a value of 0 (0 in the StringTable + // is always unused) + // so for three nodes the keys_vals array may look like this: 3 5 2 1 0 0 8 5 + // the first node has two tags (3=>5 and 2=>1), the second node does not + // have any tags and the third node has a single tag (8=>5) + for (const auto& tag : node.tags()) { + dense->add_keys_vals(string_table.record_string(tag.key())); + dense->add_keys_vals(string_table.record_string(tag.value())); + } + dense->add_keys_vals(0); + + if (m_should_add_metadata) { + // add a DenseInfo-Section to the PrimitiveGroup + OSMPBF::DenseInfo* denseinfo = dense->mutable_denseinfo(); + + denseinfo->add_version(static_cast<::google::protobuf::int32>(node.version())); + + if (m_add_visible) { + denseinfo->add_visible(node.visible()); + } + + // copy the timestamp, delta encoded + denseinfo->add_timestamp(m_delta_timestamp.update(timestamp2int(node.timestamp()))); + + // copy the changeset, delta encoded + denseinfo->add_changeset(m_delta_changeset.update(node.changeset())); + + // copy the user id, delta encoded + denseinfo->add_uid(m_delta_uid.update(node.uid())); + + // record the user-name to the interim stringtable and copy the + // interim string-id to the pbf-object + denseinfo->add_user_sid(string_table.record_string(node.user())); + } + } + + /** + * Add a way to the block. + * + * @param way The way to add. + */ + void write_way(const osmium::Way& way) { + // add a way to the group + OSMPBF::Way* pbf_way = pbf_ways->add_ways(); + + // copy the common meta-info from the osmium-object to the pbf-object + apply_common_info(way, pbf_way); + + // last way-node-id used for delta-encoding + Delta delta_id; + + for (const auto& node_ref : way.nodes()) { + // copy the way-node-id, delta encoded + pbf_way->add_refs(delta_id.update(node_ref.ref())); + } + + // count up blob size by the size of the Way + primitive_block_size += pbf_way->ByteSize(); + } + + /** + * Add a relation to the block. + * + * @param relation The relation to add. + */ + void write_relation(const osmium::Relation& relation) { + // add a relation to the group + OSMPBF::Relation* pbf_relation = pbf_relations->add_relations(); + + // copy the common meta-info from the osmium-object to the pbf-object + apply_common_info(relation, pbf_relation); + + Delta delta_id; + + for (const auto& member : relation.members()) { + // record the relation-member role to the interim stringtable and copy the + // interim string-id to the pbf-object + pbf_relation->add_roles_sid(string_table.record_string(member.role())); + + // copy the relation-member-id, delta encoded + pbf_relation->add_memids(delta_id.update(member.ref())); + + // copy the relation-member-type, mapped to the OSMPBF enum + pbf_relation->add_types(item_type_to_osmpbf_membertype(member.type())); + } + + // count up blob size by the size of the Relation + primitive_block_size += pbf_relation->ByteSize(); + } + + // objects of this class can't be copied + PBFOutputFormat(const PBFOutputFormat&) = delete; + PBFOutputFormat& operator=(const PBFOutputFormat&) = delete; + + public: + + /** + * Create PBFOutputFormat object from File. + */ + explicit PBFOutputFormat(const osmium::io::File& file, data_queue_type& output_queue) : + OutputFormat(file, output_queue), + pbf_header_block(), + pbf_primitive_block(), + pbf_nodes(nullptr), + pbf_ways(nullptr), + pbf_relations(nullptr), + m_location_granularity(pbf_primitive_block.granularity()), + m_date_granularity(pbf_primitive_block.date_granularity()), + m_add_visible(file.has_multiple_object_versions()), + primitive_block_contents(0), + primitive_block_size(0), + string_table(), + m_delta_id(), + m_delta_lat(), + m_delta_lon(), + m_delta_timestamp(), + m_delta_changeset(), + m_delta_uid(), + m_delta_user_sid(), + debug(true) { + GOOGLE_PROTOBUF_VERIFY_VERSION; + if (file.get("pbf_dense_nodes") == "false") { + m_use_dense_nodes = false; + } + if (file.get("pbf_compression") == "none" || file.get("pbf_compression") == "false") { + m_use_compression = false; + } + if (file.get("pbf_add_metadata") == "false") { + m_should_add_metadata = false; + } + } + + void write_buffer(osmium::memory::Buffer&& buffer) override final { + osmium::apply(buffer.cbegin(), buffer.cend(), *this); + } + + + /** + * getter to access the granularity + */ + int location_granularity() const { + return m_location_granularity; + } + + /** + * setter to set the granularity + */ + PBFOutputFormat& location_granularity(int g) { + m_location_granularity = g; + return *this; + } + + + /** + * getter to access the date_granularity + */ + int date_granularity() const { + return m_date_granularity; + } + + /** + * Set date granularity. + */ + PBFOutputFormat& date_granularity(int g) { + m_date_granularity = g; + return *this; + } + + + /** + * Initialize the writing process. + * + * This initializes the header-block, sets the required-features and + * the writing-program and adds the obligatory StringTable-Index 0. + */ + void write_header(const osmium::io::Header& header) override final { + // add the schema version as required feature to the HeaderBlock + pbf_header_block.add_required_features("OsmSchema-V0.6"); + + // when the densenodes-feature is used, add DenseNodes as required feature + if (m_use_dense_nodes) { + pbf_header_block.add_required_features("DenseNodes"); + } + + // when the resulting file will carry history information, add + // HistoricalInformation as required feature + if (this->m_file.has_multiple_object_versions()) { + pbf_header_block.add_required_features("HistoricalInformation"); + } + + // set the writing program + pbf_header_block.set_writingprogram(header.get("generator")); + + if (!header.boxes().empty()) { + OSMPBF::HeaderBBox* pbf_bbox = pbf_header_block.mutable_bbox(); + osmium::Box box = header.joined_boxes(); + pbf_bbox->set_left(static_cast<::google::protobuf::int64>(box.bottom_left().lon() * OSMPBF::lonlat_resolution)); + pbf_bbox->set_bottom(static_cast<::google::protobuf::int64>(box.bottom_left().lat() * OSMPBF::lonlat_resolution)); + pbf_bbox->set_right(static_cast<::google::protobuf::int64>(box.top_right().lon() * OSMPBF::lonlat_resolution)); + pbf_bbox->set_top(static_cast<::google::protobuf::int64>(box.top_right().lat() * OSMPBF::lonlat_resolution)); + } + + std::string osmosis_replication_timestamp = header.get("osmosis_replication_timestamp"); + if (!osmosis_replication_timestamp.empty()) { + osmium::Timestamp ts(osmosis_replication_timestamp.c_str()); + pbf_header_block.set_osmosis_replication_timestamp(ts); + } + + std::string osmosis_replication_sequence_number = header.get("osmosis_replication_sequence_number"); + if (!osmosis_replication_sequence_number.empty()) { + pbf_header_block.set_osmosis_replication_sequence_number(std::atoll(osmosis_replication_sequence_number.c_str())); + } + + std::string osmosis_replication_base_url = header.get("osmosis_replication_base_url"); + if (!osmosis_replication_base_url.empty()) { + pbf_header_block.set_osmosis_replication_base_url(osmosis_replication_base_url); + } + + store_header_block(); + } + + /** + * Add a node to the pbf. + * + * A call to this method won't write the node to the file directly but + * cache it for later bulk-writing. Calling final() ensures that everything + * gets written and every file pointer is closed. + */ + void node(const osmium::Node& node) { + // first of we check the contents-counter which may flush the cached nodes to + // disk if the limit is reached. This call also increases the contents-counter + check_block_contents_counter(); + + if (debug && has_debug_level(2)) { + std::cerr << "node " << node.id() << " v" << node.version() << std::endl; + } + + // if no PrimitiveGroup for nodes has been added, add one and save the pointer + if (!pbf_nodes) { + pbf_nodes = pbf_primitive_block.add_primitivegroup(); + } + + if (m_use_dense_nodes) { + write_dense_node(node); + } else { + write_node(node); + } + } + + /** + * Add a way to the pbf. + * + * A call to this method won't write the way to the file directly but + * cache it for later bulk-writing. Calling final() ensures that everything + * gets written and every file pointer is closed. + */ + void way(const osmium::Way& way) { + // first of we check the contents-counter which may flush the cached ways to + // disk if the limit is reached. This call also increases the contents-counter + check_block_contents_counter(); + + // if no PrimitiveGroup for nodes has been added, add one and save the pointer + if (!pbf_ways) { + pbf_ways = pbf_primitive_block.add_primitivegroup(); + } + + write_way(way); + } + + /** + * Add a relation to the pbf. + * + * A call to this method won't write the way to the file directly but + * cache it for later bulk-writing. Calling final() ensures that everything + * gets written and every file pointer is closed. + */ + void relation(const osmium::Relation& relation) { + // first of we check the contents-counter which may flush the cached relations to + // disk if the limit is reached. This call also increases the contents-counter + check_block_contents_counter(); + + // if no PrimitiveGroup for relations has been added, add one and save the pointer + if (!pbf_relations) { + pbf_relations = pbf_primitive_block.add_primitivegroup(); + } + + write_relation(relation); + } + + /** + * Finalize the writing process, flush any open primitive blocks to the file and + * close the file. + */ + void close() override final { + if (debug && has_debug_level(1)) { + std::cerr << "finishing" << std::endl; + } + + // if the current block contains any elements, flush it to the protobuf + if (primitive_block_contents > 0) { + store_primitive_block(); + } + + std::promise promise; + m_output_queue.push(promise.get_future()); + promise.set_value(std::string()); + } + + }; // class PBFOutputFormat + + namespace { + + const bool registered_pbf_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::pbf, + [](const osmium::io::File& file, data_queue_type& output_queue) { + return new osmium::io::detail::PBFOutputFormat(file, output_queue); + }); + + } // anonymous namespace + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_PBF_OUTPUT_FORMAT_HPP diff --git a/ThirdParty/osmium/io/detail/pbf_stringtable.hpp b/ThirdParty/osmium/io/detail/pbf_stringtable.hpp new file mode 100644 index 000000000..b1bd5cdc1 --- /dev/null +++ b/ThirdParty/osmium/io/detail/pbf_stringtable.hpp @@ -0,0 +1,196 @@ +#ifndef OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP +#define OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace osmium { + + namespace io { + + namespace detail { + + /** + * StringTable management for PBF writer + * + * All strings are stored as indexes to rows in a StringTable. The StringTable contains + * one row for each used string, so strings that are used multiple times need to be + * stored only once. The StringTable is sorted by usage-count, so the most often used + * string is stored at index 1. + */ + class StringTable { + + public: + + /// type for string IDs (interim and final) + typedef uint16_t string_id_type; + + private: + + /** + * this is the struct used to build the StringTable. It is stored as + * the value-part in the strings-map. + * + * when a new string is added to the map, its count is set to 0 and + * the interim_id is set to the current size of the map. This interim_id + * is then stored into the pbf-objects. + * + * before the PrimitiveBlock is serialized, the map is sorted by count + * and stored into the pbf-StringTable. Afterwards the interim-ids are + * mapped to the "real" id in the StringTable. + * + * this way often used strings get lower ids in the StringTable. As the + * protobuf-serializer stores numbers in variable bit-lengths, lower + * IDs means less used space in the resulting file. + */ + struct string_info { + /// number of occurrences of this string + uint16_t count; + + /// an intermediate-id + string_id_type interim_id; + }; + + /** + * Interim StringTable, storing all strings that should be written to + * the StringTable once the block is written to disk. + */ + typedef std::map string2string_info_type; + string2string_info_type m_strings; + + /** + * This vector is used to map the interim IDs to real StringTable IDs after + * writing all strings to the StringTable. + */ + typedef std::vector interim_id2id_type; + interim_id2id_type m_id2id_map; + + size_t m_size = 0; + + public: + + StringTable() { + } + + friend bool operator<(const string_info& lhs, const string_info& rhs) { + return lhs.count > rhs.count; + } + + /** + * record a string in the interim StringTable if it's missing, otherwise just increase its counter, + * return the interim-id assigned to the string. + */ + string_id_type record_string(const std::string& string) { + string_info& info = m_strings[string]; + if (info.interim_id == 0) { + ++m_size; + assert(m_size < std::numeric_limits::max()); + info.interim_id = static_cast(m_size); + } else { + info.count++; + } + return info.interim_id; + } + + /** + * Sort the interim StringTable and store it to the real protobuf StringTable. + * while storing to the real table, this function fills the id2id_map with + * pairs, mapping the interim-ids to final and real StringTable ids. + * + * Note that the m_strings table is a std::map and as such is sorted lexicographically. + * When the transformation into the sortedby multimap is done, it gets sorted by + * the count. The end result (at least with the glibc standard container/algorithm + * implementation) is that the string table is sorted first by reverse count (ie descending) + * and then by reverse lexicographic order. + */ + void store_stringtable(OSMPBF::StringTable* st) { + // add empty StringTable entry at index 0 + // StringTable index 0 is reserved as delimiter in the densenodes key/value list + // this line also ensures that there's always a valid StringTable + st->add_s(""); + + std::multimap sortedbycount; + + m_id2id_map.resize(m_size+1); + + std::transform(m_strings.begin(), m_strings.end(), + std::inserter(sortedbycount, sortedbycount.begin()), + [](const std::pair& p) { + return std::pair(p.second, p.first); + }); + + string_id_type n=0; + + for (const auto& mapping : sortedbycount) { + // add the string of the current item to the pbf StringTable + st->add_s(mapping.second); + + // store the mapping from the interim-id to the real id + m_id2id_map[mapping.first.interim_id] = ++n; + } + } + + /** + * Map from an interim ID to a real string ID. + */ + string_id_type map_string_id(const string_id_type interim_id) const { + return m_id2id_map[interim_id]; + } + + /** + * Clear the stringtable, preparing for the next block. + */ + void clear() { + m_strings.clear(); + m_id2id_map.clear(); + m_size = 0; + } + + }; // class StringTable + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_PBF_STRINGTABLE_HPP diff --git a/ThirdParty/osmium/io/detail/read_thread.hpp b/ThirdParty/osmium/io/detail/read_thread.hpp new file mode 100644 index 000000000..eb8461261 --- /dev/null +++ b/ThirdParty/osmium/io/detail/read_thread.hpp @@ -0,0 +1,105 @@ +#ifndef OSMIUM_IO_DETAIL_READ_THREAD_HPP +#define OSMIUM_IO_DETAIL_READ_THREAD_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace osmium { + + namespace io { + + namespace detail { + + class ReadThread { + + osmium::thread::Queue& m_queue; + osmium::io::Decompressor* m_decompressor; + + // If this is set in the main thread, we have to wrap up at the + // next possible moment. + std::atomic& m_done; + + public: + + explicit ReadThread(osmium::thread::Queue& queue, osmium::io::Decompressor* decompressor, std::atomic& done) : + m_queue(queue), + m_decompressor(decompressor), + m_done(done) { + } + + bool operator()() { + osmium::thread::set_thread_name("_osmium_input"); + + try { + while (!m_done) { + std::string data {m_decompressor->read()}; + if (data.empty()) { + m_done = true; + } + m_queue.push(std::move(data)); + while (m_queue.size() > 10) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } + + m_decompressor->close(); + } catch (...) { + // If there is an exception in this thread, we make sure + // to push an empty string onto the queue to signal the + // end-of-data to the reading thread so that it will not + // hang. Then we re-throw the exception. + m_queue.push(std::string()); + throw; + } + return true; + } + + }; // class ReadThread + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_READ_THREAD_HPP diff --git a/ThirdParty/osmium/io/detail/read_write.hpp b/ThirdParty/osmium/io/detail/read_write.hpp new file mode 100644 index 000000000..305e63b11 --- /dev/null +++ b/ThirdParty/osmium/io/detail/read_write.hpp @@ -0,0 +1,170 @@ +#ifndef OSMIUM_IO_DETAIL_READ_WRITE_HPP +#define OSMIUM_IO_DETAIL_READ_WRITE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +//#include +//#include +#include +#ifndef _MSC_VER +#include +#else +#include +typedef int ssize_t; +#endif + +#include + +namespace osmium { + + namespace io { + + /** + * @brief Namespace for Osmium internal use + */ + namespace detail { + + /** + * Open file for writing. If the file exists, it is truncated, if + * not, it is created. If the file name is empty or "-", no file + * is open and the stdout file descriptor (1) is returned. + * + * @param filename Name of file to be opened. + * @param allow_overwrite If the file exists, should it be overwritten? + * @return File descriptor of open file. + * @throws system_error if the file can't be opened. + */ + inline int open_for_writing(const std::string& filename, osmium::io::overwrite allow_overwrite = osmium::io::overwrite::no) { + if (filename == "" || filename == "-") { + return 1; // stdout + } else { + int flags = O_WRONLY | O_CREAT; + if (allow_overwrite == osmium::io::overwrite::allow) { + flags |= O_TRUNC; + } else { + flags |= O_EXCL; + } +#ifdef WIN32 + flags |= O_BINARY; +#endif + int fd = ::open(filename.c_str(), flags, 0666); + if (fd < 0) { + throw std::system_error(errno, std::system_category(), std::string("Open failed for '") + filename + "'"); + } + return fd; + } + } + + /** + * Open file for reading. If the file name is empty or "-", no file + * is open and the stdin file descriptor (0) is returned. + * + * @return File descriptor of open file. + * @throws system_error if the file can't be opened. + */ + inline int open_for_reading(const std::string& filename) { + if (filename == "" || filename == "-") { + return 0; // stdin + } else { + int flags = O_RDONLY; +#ifdef WIN32 + flags |= O_BINARY; +#endif + int fd = ::open(filename.c_str(), flags); + if (fd < 0) { + throw std::system_error(errno, std::system_category(), std::string("Open failed for '") + filename + "'"); + } + return fd; + } + } + + /** + * Reads the given number of bytes into the input buffer. + * This is basically just a wrapper around read(2). + * + * @param fd File descriptor. + * @param input_buffer Buffer with data of at least size. + * @param size Number of bytes to be read. + * @return True when read was successful, false on EOF. + * @exception std::system_error On error. + */ + inline bool reliable_read(const int fd, unsigned char* input_buffer, const size_t size) { + size_t offset = 0; + while (offset < size) { + ssize_t length = ::read(fd, input_buffer + offset, size - offset); + if (length < 0) { + throw std::system_error(errno, std::system_category(), "Read failed"); + } + if (length == 0) { + return false; + } + offset += static_cast(length); + } + return true; + } + + /** + * Writes the given number of bytes from the output_buffer to the file descriptor. + * This is just a wrapper around write(2). + * + * @param fd File descriptor. + * @param output_buffer Buffer where data is written. Must be at least size bytes long. + * @param size Number of bytes to be read. + * @exception std::system_error On error. + */ + inline void reliable_write(const int fd, const unsigned char* output_buffer, const size_t size) { + size_t offset = 0; + do { + ssize_t length = ::write(fd, output_buffer + offset, size - offset); + if (length < 0) { + throw std::system_error(errno, std::system_category(), "Write failed"); + } + offset += static_cast(length); + } while (offset < size); + } + + inline void reliable_write(const int fd, const char* output_buffer, const size_t size) { + reliable_write(fd, reinterpret_cast(output_buffer), size); + } + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_READ_WRITE_HPP diff --git a/ThirdParty/osmium/io/detail/write_thread.hpp b/ThirdParty/osmium/io/detail/write_thread.hpp new file mode 100644 index 000000000..599851f0c --- /dev/null +++ b/ThirdParty/osmium/io/detail/write_thread.hpp @@ -0,0 +1,86 @@ +#ifndef OSMIUM_IO_DETAIL_WRITE_THREAD_HPP +#define OSMIUM_IO_DETAIL_WRITE_THREAD_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include +#include +#include + +namespace osmium { + + namespace io { + + namespace detail { + + class WriteThread { + + typedef osmium::io::detail::data_queue_type data_queue_type; + + data_queue_type& m_input_queue; + osmium::io::Compressor* m_compressor; + + public: + + explicit WriteThread(data_queue_type& input_queue, osmium::io::Compressor* compressor) : + m_input_queue(input_queue), + m_compressor(compressor) { + } + + bool operator()() { + osmium::thread::set_thread_name("_osmium_output"); + + std::future data_future; + std::string data; + do { + m_input_queue.wait_and_pop(data_future); + data = data_future.get(); + m_compressor->write(data); + } while (!data.empty()); + + m_compressor->close(); + return true; + } + + }; // class WriteThread + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_WRITE_THREAD_HPP diff --git a/ThirdParty/osmium/io/detail/xml_input_format.hpp b/ThirdParty/osmium/io/detail/xml_input_format.hpp new file mode 100644 index 000000000..461a947cd --- /dev/null +++ b/ThirdParty/osmium/io/detail/xml_input_format.hpp @@ -0,0 +1,677 @@ +#ifndef OSMIUM_IO_DETAIL_XML_INPUT_FORMAT_HPP +#define OSMIUM_IO_DETAIL_XML_INPUT_FORMAT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#define OSMIUM_LINK_WITH_LIBS_EXPAT -lexpat + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + struct xml_error : public io_error { + + unsigned long line; + unsigned long column; + XML_Error error_code; + std::string error_string; + + xml_error(XML_Parser parser) : + io_error(std::string("XML parsing error at line ") + + std::to_string(XML_GetCurrentLineNumber(parser)) + + ", column " + + std::to_string(XML_GetCurrentColumnNumber(parser)) + + ": " + + XML_ErrorString(XML_GetErrorCode(parser))), + line(XML_GetCurrentLineNumber(parser)), + column(XML_GetCurrentColumnNumber(parser)), + error_code(XML_GetErrorCode(parser)), + error_string(XML_ErrorString(error_code)) { + } + + }; // struct xml_error + + struct format_version_error : public io_error { + + std::string version; + + explicit format_version_error() : + io_error("Can not read file without version (missing version attribute on osm element)."), + version() { + } + + explicit format_version_error(const char* v) : + io_error(std::string("Can not read file with version ") + v), + version(v) { + } + + }; // struct format_version_error + + namespace io { + + class File; + + namespace detail { + + /** + * Once the header is fully parsed this exception will be thrown if + * the caller is not interested in anything else except the header. + * It will break off the parsing at this point. + */ + class ParserIsDone : std::exception { + }; + + class XMLParser { + + static constexpr int buffer_size = 10 * 1000 * 1000; + + enum class context { + root, + top, + node, + way, + relation, + changeset, + ignored_node, + ignored_way, + ignored_relation, + ignored_changeset, + in_object + }; + + context m_context; + context m_last_context; + + /** + * This is used only for change files which contain create, modify, + * and delete sections. + */ + bool m_in_delete_section; + + osmium::io::Header m_header; + + osmium::memory::Buffer m_buffer; + + std::unique_ptr m_node_builder; + std::unique_ptr m_way_builder; + std::unique_ptr m_relation_builder; + std::unique_ptr m_changeset_builder; + + std::unique_ptr m_tl_builder; + std::unique_ptr m_wnl_builder; + std::unique_ptr m_rml_builder; + + osmium::thread::Queue& m_input_queue; + osmium::thread::Queue& m_queue; + std::promise& m_header_promise; + + bool m_promise_fulfilled; + + osmium::osm_entity_bits::type m_read_types; + + size_t m_max_queue_size; + + std::atomic& m_done; + + public: + + explicit XMLParser(osmium::thread::Queue& input_queue, osmium::thread::Queue& queue, std::promise& header_promise, osmium::osm_entity_bits::type read_types, std::atomic& done) : + m_context(context::root), + m_last_context(context::root), + m_in_delete_section(false), + m_header(), + m_buffer(buffer_size), + m_node_builder(), + m_way_builder(), + m_relation_builder(), + m_changeset_builder(), + m_tl_builder(), + m_wnl_builder(), + m_rml_builder(), + m_input_queue(input_queue), + m_queue(queue), + m_header_promise(header_promise), + m_promise_fulfilled(false), + m_read_types(read_types), + m_max_queue_size(100), + m_done(done) { + } + + /** + * The copy constructor is needed for storing XMLParser in a std::function. + * The copy will look the same as if it has been initialized with the + * same parameters as the original. Any state changes in the original will + * not be reflected in the copy. + */ + XMLParser(const XMLParser& other) : + m_context(context::root), + m_last_context(context::root), + m_in_delete_section(false), + m_header(), + m_buffer(buffer_size), + m_node_builder(), + m_way_builder(), + m_relation_builder(), + m_changeset_builder(), + m_tl_builder(), + m_wnl_builder(), + m_rml_builder(), + m_input_queue(other.m_input_queue), + m_queue(other.m_queue), + m_header_promise(other.m_header_promise), + m_promise_fulfilled(false), + m_read_types(other.m_read_types), + m_max_queue_size(100), + m_done(other.m_done) { + } + + XMLParser(XMLParser&& other) = default; + + XMLParser& operator=(const XMLParser&) = delete; + + XMLParser& operator=(XMLParser&& other) = default; + + ~XMLParser() = default; + + bool operator()() { + XML_Parser parser = XML_ParserCreate(nullptr); + if (!parser) { + throw osmium::io_error("Internal error: Can not create parser"); + } + + XML_SetUserData(parser, this); + + XML_SetElementHandler(parser, start_element_wrapper, end_element_wrapper); + + try { + int done; + do { + std::string data; + m_input_queue.wait_and_pop(data); + done = data.empty(); + try { + if (XML_Parse(parser, data.data(), data.size(), done) == XML_STATUS_ERROR) { + throw osmium::xml_error(parser); + } + } catch (ParserIsDone&) { + throw; + } catch (...) { + m_queue.push(osmium::memory::Buffer()); // empty buffer to signify eof + if (!m_promise_fulfilled) { + m_promise_fulfilled = true; + m_header_promise.set_value(m_header); + } + throw; + } + } while (!done && !m_done); + header_is_done(); // make sure we'll always fulfill the promise + if (m_buffer.committed() > 0) { + m_queue.push(std::move(m_buffer)); + } + m_queue.push(osmium::memory::Buffer()); // empty buffer to signify eof + } catch (ParserIsDone&) { + // intentionally left blank + } + XML_ParserFree(parser); + return true; + } + + private: + + static void XMLCALL start_element_wrapper(void* data, const XML_Char* element, const XML_Char** attrs) { + static_cast(data)->start_element(element, attrs); + } + + static void XMLCALL end_element_wrapper(void* data, const XML_Char* element) { + static_cast(data)->end_element(element); + } + + const char* init_object(osmium::OSMObject& object, const XML_Char** attrs) { + static const char* empty = ""; + const char* user = empty; + + if (m_in_delete_section) { + object.visible(false); + } + for (int count = 0; attrs[count]; count += 2) { + if (!strcmp(attrs[count], "lon")) { + static_cast(object).location().lon(std::atof(attrs[count+1])); // XXX doesn't detect garbage after the number + } else if (!strcmp(attrs[count], "lat")) { + static_cast(object).location().lat(std::atof(attrs[count+1])); // XXX doesn't detect garbage after the number + } else if (!strcmp(attrs[count], "user")) { + user = attrs[count+1]; + } else { + object.set_attribute(attrs[count], attrs[count+1]); + } + } + + return user; + } + + void init_changeset(osmium::builder::ChangesetBuilder* builder, const XML_Char** attrs) { + static const char* empty = ""; + const char* user = empty; + osmium::Changeset& new_changeset = builder->object(); + + osmium::Location min; + osmium::Location max; + for (int count = 0; attrs[count]; count += 2) { + if (!strcmp(attrs[count], "min_lon")) { + min.lon(atof(attrs[count+1])); + } else if (!strcmp(attrs[count], "min_lat")) { + min.lat(atof(attrs[count+1])); + } else if (!strcmp(attrs[count], "max_lon")) { + max.lon(atof(attrs[count+1])); + } else if (!strcmp(attrs[count], "max_lat")) { + max.lat(atof(attrs[count+1])); + } else if (!strcmp(attrs[count], "user")) { + user = attrs[count+1]; + } else { + new_changeset.set_attribute(attrs[count], attrs[count+1]); + } + } + + new_changeset.bounds().extend(min); + new_changeset.bounds().extend(max); + + builder->add_user(user); + } + + void check_tag(osmium::builder::Builder* builder, const XML_Char* element, const XML_Char** attrs) { + if (!strcmp(element, "tag")) { + m_wnl_builder.reset(); + m_rml_builder.reset(); + + const char* key = ""; + const char* value = ""; + for (int count = 0; attrs[count]; count += 2) { + if (attrs[count][0] == 'k' && attrs[count][1] == 0) { + key = attrs[count+1]; + } + if (attrs[count][0] == 'v' && attrs[count][1] == 0) { + value = attrs[count+1]; + } + } + if (!m_tl_builder) { + m_tl_builder = std::unique_ptr(new osmium::builder::TagListBuilder(m_buffer, builder)); + } + m_tl_builder->add_tag(key, value); + } + } + + void header_is_done() { + if (!m_promise_fulfilled) { + m_header_promise.set_value(m_header); + m_promise_fulfilled = true; + if (m_read_types == osmium::osm_entity_bits::nothing) { + throw ParserIsDone(); + } + } + } + + void start_element(const XML_Char* element, const XML_Char** attrs) { + switch (m_context) { + case context::root: + if (!strcmp(element, "osm") || !strcmp(element, "osmChange")) { + if (!strcmp(element, "osmChange")) { + m_header.has_multiple_object_versions(true); + } + for (int count = 0; attrs[count]; count += 2) { + if (!strcmp(attrs[count], "version")) { + m_header.set("version", attrs[count+1]); + if (strcmp(attrs[count+1], "0.6")) { + throw osmium::format_version_error(attrs[count+1]); + } + } else if (!strcmp(attrs[count], "generator")) { + m_header.set("generator", attrs[count+1]); + } + } + if (m_header.get("version") == "") { + throw osmium::format_version_error(); + } + } + m_context = context::top; + break; + case context::top: + assert(!m_tl_builder); + if (!strcmp(element, "node")) { + header_is_done(); + if (m_read_types & osmium::osm_entity_bits::node) { + m_node_builder = std::unique_ptr(new osmium::builder::NodeBuilder(m_buffer)); + m_node_builder->add_user(init_object(m_node_builder->object(), attrs)); + m_context = context::node; + } else { + m_context = context::ignored_node; + } + } else if (!strcmp(element, "way")) { + header_is_done(); + if (m_read_types & osmium::osm_entity_bits::way) { + m_way_builder = std::unique_ptr(new osmium::builder::WayBuilder(m_buffer)); + m_way_builder->add_user(init_object(m_way_builder->object(), attrs)); + m_context = context::way; + } else { + m_context = context::ignored_way; + } + } else if (!strcmp(element, "relation")) { + header_is_done(); + if (m_read_types & osmium::osm_entity_bits::relation) { + m_relation_builder = std::unique_ptr(new osmium::builder::RelationBuilder(m_buffer)); + m_relation_builder->add_user(init_object(m_relation_builder->object(), attrs)); + m_context = context::relation; + } else { + m_context = context::ignored_relation; + } + } else if (!strcmp(element, "changeset")) { + header_is_done(); + if (m_read_types & osmium::osm_entity_bits::changeset) { + m_changeset_builder = std::unique_ptr(new osmium::builder::ChangesetBuilder(m_buffer)); + init_changeset(m_changeset_builder.get(), attrs); + m_context = context::changeset; + } else { + m_context = context::ignored_changeset; + } + } else if (!strcmp(element, "bounds")) { + osmium::Location min; + osmium::Location max; + for (int count = 0; attrs[count]; count += 2) { + if (!strcmp(attrs[count], "minlon")) { + min.lon(atof(attrs[count+1])); + } else if (!strcmp(attrs[count], "minlat")) { + min.lat(atof(attrs[count+1])); + } else if (!strcmp(attrs[count], "maxlon")) { + max.lon(atof(attrs[count+1])); + } else if (!strcmp(attrs[count], "maxlat")) { + max.lat(atof(attrs[count+1])); + } + } + osmium::Box box; + box.extend(min).extend(max); + m_header.add_box(box); + } else if (!strcmp(element, "delete")) { + m_in_delete_section = true; + } + break; + case context::node: + m_last_context = context::node; + m_context = context::in_object; + check_tag(m_node_builder.get(), element, attrs); + break; + case context::way: + m_last_context = context::way; + m_context = context::in_object; + if (!strcmp(element, "nd")) { + m_tl_builder.reset(); + + if (!m_wnl_builder) { + m_wnl_builder = std::unique_ptr(new osmium::builder::WayNodeListBuilder(m_buffer, m_way_builder.get())); + } + + for (int count = 0; attrs[count]; count += 2) { + if (!strcmp(attrs[count], "ref")) { + m_wnl_builder->add_node_ref(osmium::string_to_object_id(attrs[count+1])); + } + } + } else { + check_tag(m_way_builder.get(), element, attrs); + } + break; + case context::relation: + m_last_context = context::relation; + m_context = context::in_object; + if (!strcmp(element, "member")) { + m_tl_builder.reset(); + + if (!m_rml_builder) { + m_rml_builder = std::unique_ptr(new osmium::builder::RelationMemberListBuilder(m_buffer, m_relation_builder.get())); + } + + char type = 'x'; + object_id_type ref = 0; + const char* role = ""; + for (int count = 0; attrs[count]; count += 2) { + if (!strcmp(attrs[count], "type")) { + type = static_cast(attrs[count+1][0]); + } else if (!strcmp(attrs[count], "ref")) { + ref = osmium::string_to_object_id(attrs[count+1]); + } else if (!strcmp(attrs[count], "role")) { + role = static_cast(attrs[count+1]); + } + } + // XXX assert type, ref, role are set + m_rml_builder->add_member(char_to_item_type(type), ref, role); + } else { + check_tag(m_relation_builder.get(), element, attrs); + } + break; + case context::changeset: + m_last_context = context::changeset; + m_context = context::in_object; + check_tag(m_changeset_builder.get(), element, attrs); + break; + case context::ignored_node: + break; + case context::ignored_way: + break; + case context::ignored_relation: + break; + case context::ignored_changeset: + break; + case context::in_object: + assert(false); // should never be here + break; + } + } + + void end_element(const XML_Char* element) { + switch (m_context) { + case context::root: + assert(false); // should never be here + break; + case context::top: + if (!strcmp(element, "osm") || !strcmp(element, "osmChange")) { + header_is_done(); + m_context = context::root; + } else if (!strcmp(element, "delete")) { + m_in_delete_section = false; + } + break; + case context::node: + assert(!strcmp(element, "node")); + m_tl_builder.reset(); + m_node_builder.reset(); + m_buffer.commit(); + m_context = context::top; + flush_buffer(); + break; + case context::way: + assert(!strcmp(element, "way")); + m_tl_builder.reset(); + m_wnl_builder.reset(); + m_way_builder.reset(); + m_buffer.commit(); + m_context = context::top; + flush_buffer(); + break; + case context::relation: + assert(!strcmp(element, "relation")); + m_tl_builder.reset(); + m_rml_builder.reset(); + m_relation_builder.reset(); + m_buffer.commit(); + m_context = context::top; + flush_buffer(); + break; + case context::changeset: + assert(!strcmp(element, "changeset")); + m_tl_builder.reset(); + m_changeset_builder.reset(); + m_buffer.commit(); + m_context = context::top; + flush_buffer(); + break; + case context::in_object: + m_context = m_last_context; + break; + case context::ignored_node: + if (!strcmp(element, "node")) { + m_context = context::top; + } + break; + case context::ignored_way: + if (!strcmp(element, "way")) { + m_context = context::top; + } + break; + case context::ignored_relation: + if (!strcmp(element, "relation")) { + m_context = context::top; + } + break; + case context::ignored_changeset: + if (!strcmp(element, "changeset")) { + m_context = context::top; + } + break; + } + } + + void flush_buffer() { + if (m_buffer.capacity() - m_buffer.committed() < 1000 * 1000) { + m_queue.push(std::move(m_buffer)); + osmium::memory::Buffer buffer(buffer_size); + std::swap(m_buffer, buffer); + + while (m_queue.size() > m_max_queue_size) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } + } + + }; // XMLParser + + class XMLInputFormat : public osmium::io::detail::InputFormat { + + static constexpr size_t m_max_queue_size = 100; + + osmium::thread::Queue m_queue; + std::atomic m_done; + std::promise m_header_promise; + osmium::thread::CheckedTask m_parser_task; + + public: + + /** + * Instantiate XML Parser + * + * @param file osmium::io::File instance describing file to be read from. + * @param read_which_entities Which types of OSM entities (nodes, ways, relations, changesets) should be parsed? + * @param input_queue String queue where data is read from. + */ + explicit XMLInputFormat(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) : + osmium::io::detail::InputFormat(file, read_which_entities, input_queue), + m_queue(), + m_done(false), + m_header_promise(), + m_parser_task(input_queue, m_queue, m_header_promise, read_which_entities, m_done) { + } + + ~XMLInputFormat() { + m_done = true; + } + + virtual osmium::io::Header header() override final { + m_parser_task.check_for_exception(); + return m_header_promise.get_future().get(); + } + + osmium::memory::Buffer read() override { + osmium::memory::Buffer buffer; + if (!m_done || !m_queue.empty()) { + m_queue.wait_and_pop(buffer); + } + + m_parser_task.check_for_exception(); + return buffer; + } + + }; // class XMLInputFormat + + namespace { + + const bool registered_xml_input = osmium::io::detail::InputFormatFactory::instance().register_input_format(osmium::io::file_format::xml, + [](const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue& input_queue) { + return new osmium::io::detail::XMLInputFormat(file, read_which_entities, input_queue); + }); + + } // anonymous namespace + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_XML_INPUT_FORMAT_HPP diff --git a/ThirdParty/osmium/io/detail/xml_output_format.hpp b/ThirdParty/osmium/io/detail/xml_output_format.hpp new file mode 100644 index 000000000..fc9e1e630 --- /dev/null +++ b/ThirdParty/osmium/io/detail/xml_output_format.hpp @@ -0,0 +1,482 @@ +#ifndef OSMIUM_IO_DETAIL_XML_OUTPUT_FORMAT_HPP +#define OSMIUM_IO_DETAIL_XML_OUTPUT_FORMAT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace io { + + namespace detail { + + struct XMLWriteError {}; + + namespace { + + void xml_string(std::string& out, const char* in) { + for (; *in != '\0'; ++in) { + switch(*in) { + case '&': out += "&"; break; + case '\"': out += """; break; + case '\'': out += "'"; break; + case '<': out += "<"; break; + case '>': out += ">"; break; + default: out += *in; break; + } + } + } + + const size_t tmp_buffer_size = 100; + + template + void oprintf(std::string& out, const char* format, T value) { + char buffer[tmp_buffer_size+1]; + size_t max_size = sizeof(buffer)/sizeof(char); +#ifndef _MSC_VER + int len = snprintf(buffer, max_size, format, value); +#else + int len = _snprintf(buffer, max_size, format, value); +#endif + assert(len > 0 && static_cast(len) < max_size); + out += buffer; + } + + } // anonymous namespace + + class XMLOutputBlock : public osmium::handler::Handler { + + // operation (create, modify, delete) for osc files + enum class operation { + op_none = 0, + op_create = 1, + op_modify = 2, + op_delete = 3 + }; + + osmium::memory::Buffer m_input_buffer; + + std::string m_out; + + operation m_last_op {operation::op_none}; + + const bool m_write_visible_flag; + const bool m_write_change_ops; + + void write_spaces(int num) { + for (; num!=0; --num) { + m_out += ' '; + } + } + + void write_prefix() { + if (m_write_change_ops) { + write_spaces(4); + } else { + write_spaces(2); + } + } + + void write_meta(const osmium::OSMObject& object) { + oprintf(m_out, " id=\"%" PRId64 "\"", object.id()); + + if (object.version()) { + oprintf(m_out, " version=\"%d\"", object.version()); + } + + if (object.timestamp()) { + m_out += " timestamp=\""; + m_out += object.timestamp().to_iso(); + m_out += "\""; + } + + if (!object.user_is_anonymous()) { + oprintf(m_out, " uid=\"%d\" user=\"", object.uid()); + xml_string(m_out, object.user()); + m_out += "\""; + } + + if (object.changeset()) { + oprintf(m_out, " changeset=\"%d\"", object.changeset()); + } + + if (m_write_visible_flag) { + if (object.visible()) { + m_out += " visible=\"true\""; + } else { + m_out += " visible=\"false\""; + } + } + } + + void write_tags(const osmium::TagList& tags) { + for (const auto& tag : tags) { + write_prefix(); + m_out += " \n"; + } + } + + void open_close_op_tag(const operation op = operation::op_none) { + if (op == m_last_op) { + return; + } + + switch (m_last_op) { + case operation::op_none: + break; + case operation::op_create: + m_out += " \n"; + break; + case operation::op_modify: + m_out += " \n"; + break; + case operation::op_delete: + m_out += " \n"; + break; + } + + switch (op) { + case operation::op_none: + break; + case operation::op_create: + m_out += " \n"; + break; + case operation::op_modify: + m_out += " \n"; + break; + case operation::op_delete: + m_out += " \n"; + break; + } + + m_last_op = op; + } + + public: + + explicit XMLOutputBlock(osmium::memory::Buffer&& buffer, bool write_visible_flag, bool write_change_ops) : + m_input_buffer(std::move(buffer)), + m_write_visible_flag(write_visible_flag && !write_change_ops), + m_write_change_ops(write_change_ops) { + } + + XMLOutputBlock(const XMLOutputBlock&) = delete; + XMLOutputBlock& operator=(const XMLOutputBlock&) = delete; + + XMLOutputBlock(XMLOutputBlock&& other) = default; + XMLOutputBlock& operator=(XMLOutputBlock&& other) = default; + + std::string operator()() { + osmium::apply(m_input_buffer.cbegin(), m_input_buffer.cend(), *this); + + if (m_write_change_ops) { + open_close_op_tag(); + } + + std::string out; + std::swap(out, m_out); + return out; + } + + void node(const osmium::Node& node) { + if (m_write_change_ops) { + open_close_op_tag(node.visible() ? (node.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete); + } + + write_prefix(); + m_out += "\n", node_ref.ref()); + } + + write_tags(way.tags()); + + write_prefix(); + m_out += "\n"; + } + + void relation(const osmium::Relation& relation) { + if (m_write_change_ops) { + open_close_op_tag(relation.visible() ? (relation.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete); + } + + write_prefix(); + m_out += "\n"; + } + + write_tags(relation.tags()); + + write_prefix(); + m_out += "\n"; + } + + void changeset(const osmium::Changeset& changeset) { + write_prefix(); + m_out += " 10) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // XXX + } + } + + void write_header(const osmium::io::Header& header) override final { + std::string out = "\n"; + + if (m_file.is_true("xml_change_format")) { + out += "\n"; + } else { + out += "\n"; + } + + for (const auto& box : header.boxes()) { + out += " \n", box.top_right().lat()); + } + + std::promise promise; + m_output_queue.push(promise.get_future()); + promise.set_value(std::move(out)); + } + + void close() override final { + { + std::string out; + if (m_file.is_true("xml_change_format")) { + out += "\n"; + } else { + out += "\n"; + } + + std::promise promise; + m_output_queue.push(promise.get_future()); + promise.set_value(std::move(out)); + } + + std::promise promise; + m_output_queue.push(promise.get_future()); + promise.set_value(std::string()); + } + + }; // class XMLOutputFormat + + namespace { + + const bool registered_xml_output = osmium::io::detail::OutputFormatFactory::instance().register_output_format(osmium::io::file_format::xml, + [](const osmium::io::File& file, data_queue_type& output_queue) { + return new osmium::io::detail::XMLOutputFormat(file, output_queue); + }); + + } // anonymous namespace + + } // namespace detail + + } // namespace output + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_XML_OUTPUT_FORMAT_HPP diff --git a/ThirdParty/osmium/io/detail/zlib.hpp b/ThirdParty/osmium/io/detail/zlib.hpp new file mode 100644 index 000000000..932c04835 --- /dev/null +++ b/ThirdParty/osmium/io/detail/zlib.hpp @@ -0,0 +1,98 @@ +#ifndef OSMIUM_IO_DETAIL_ZLIB_HPP +#define OSMIUM_IO_DETAIL_ZLIB_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#define OSMIUM_LINK_WITH_LIBS_ZLIB -lz + +#include +#include + +#include + +namespace osmium { + + namespace io { + + namespace detail { + + /** + * Compress data using zlib. + * + * @param input Data to compress. + * @return Compressed data. + */ + inline std::string zlib_compress(const std::string& input) { + unsigned long output_size = ::compressBound(input.size()); + + std::string output(output_size, '\0'); + + if (::compress(reinterpret_cast(const_cast(output.data())), + &output_size, + reinterpret_cast(input.data()), + input.size()) != Z_OK) { + throw std::runtime_error("failed to compress data"); + } + + output.resize(output_size); + + return output; + } + + /** + * Uncompress data using zlib. + * + * @param input Compressed input data. + * @param raw_size Size of uncompressed data. + * @return Uncompressed data. + */ + inline std::string zlib_uncompress(const std::string& input, unsigned long raw_size) { + std::string output(raw_size, '\0'); + + if (::uncompress(reinterpret_cast(const_cast(output.data())), + &raw_size, + reinterpret_cast(input.data()), + input.size()) != Z_OK) { + throw std::runtime_error("failed to uncompress data"); + } + + return output; + } + + } // namespace detail + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_DETAIL_ZLIB_HPP diff --git a/ThirdParty/osmium/io/file.hpp b/ThirdParty/osmium/io/file.hpp new file mode 100644 index 000000000..3aa76f77a --- /dev/null +++ b/ThirdParty/osmium/io/file.hpp @@ -0,0 +1,319 @@ +#ifndef OSMIUM_IO_FILE_HPP +#define OSMIUM_IO_FILE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace osmium { + + struct io_error : public std::runtime_error { + + io_error(const std::string& what) : + std::runtime_error(what) { + } + + io_error(const char* what) : + std::runtime_error(what) { + } + + }; // struct io_error + + /** + * @brief Everything related to input and output of OSM data. + */ + namespace io { + + namespace detail { + + inline std::vector split(const std::string& in, const char delim) { + std::vector result; + std::stringstream ss(in); + std::string item; + while (std::getline(ss, item, delim)) { + result.push_back(item); + } + return result; + } + + } // namespace detail + + /** + * This class describes an OSM file in one of several different formats. + * + * If the filename is empty or "-", this means stdin or stdout is used. + */ + class File : public osmium::util::Options { + + private: + + std::string m_filename; + + std::string m_format_string; + + file_format m_file_format {file_format::unknown}; + + file_compression m_file_compression {file_compression::none}; + + bool m_has_multiple_object_versions {false}; + + public: + + /** + * Create File using type and encoding from filename or given + * format specification. + * + * @param filename Filename including suffix. The type and encoding + * of the file will be taken from the suffix. + * An empty filename or "-" means stdin or stdout. + * @param format File format as string. See the description of the + * parse_format() function for details. + */ + explicit File(const std::string& filename = "", const std::string& format = "") : + Options(), + m_filename(filename), + m_format_string(format) { + + // stdin/stdout + if (filename == "" || filename == "-") { + m_filename = ""; + default_settings_for_stdinout(); + } + + // filename is actually a URL + std::string protocol = m_filename.substr(0, m_filename.find_first_of(':')); + if (protocol == "http" || protocol == "https") { + default_settings_for_url(); + } + + detect_format_from_suffix(m_filename); + + if (format != "") { + parse_format(format); + } + } + + File(const File& other) = default; + File& operator=(const File& other) = default; + + File(File&& other) = default; + File& operator=(File&& other) = default; + + ~File() = default; + + void parse_format(const std::string& format) { + std::vector options = detail::split(format, ','); + + // if the first item in the format list doesn't contain + // an equals sign, it is a format + if (!options.empty() && options[0].find_first_of('=') == std::string::npos) { + detect_format_from_suffix(options[0]); + options.erase(options.begin()); + } + + for (auto& option : options) { + size_t pos = option.find_first_of('='); + if (pos == std::string::npos) { + set(option, true); + } else { + std::string value = option.substr(pos+1); + option.erase(pos); + set(option, value); + } + } + + if (get("history") == "true") { + m_has_multiple_object_versions = true; + } else if (get("history") == "false") { + m_has_multiple_object_versions = false; + } + } + + void detect_format_from_suffix(const std::string& name) { + std::vector suffixes = detail::split(name, '.'); + + if (suffixes.empty()) return; + + // if the last suffix is one of a known set of compressions, + // set that compression + if (suffixes.back() == "gz") { + m_file_compression = file_compression::gzip; + suffixes.pop_back(); + } else if (suffixes.back() == "bz2") { + m_file_compression = file_compression::bzip2; + suffixes.pop_back(); + } + + if (suffixes.empty()) return; + + // if the last suffix is one of a known set of formats, + // set that format + if (suffixes.back() == "pbf") { + m_file_format = file_format::pbf; + suffixes.pop_back(); + } else if (suffixes.back() == "xml") { + m_file_format = file_format::xml; + suffixes.pop_back(); + } else if (suffixes.back() == "opl") { + m_file_format = file_format::opl; + suffixes.pop_back(); + } + + if (suffixes.empty()) return; + + if (suffixes.back() == "osm") { + if (m_file_format == file_format::unknown) m_file_format = file_format::xml; + suffixes.pop_back(); + } else if (suffixes.back() == "osh") { + if (m_file_format == file_format::unknown) m_file_format = file_format::xml; + m_has_multiple_object_versions = true; + suffixes.pop_back(); + } else if (suffixes.back() == "osc") { + if (m_file_format == file_format::unknown) m_file_format = file_format::xml; + m_has_multiple_object_versions = true; + set("xml_change_format", true); + suffixes.pop_back(); + } + } + + /** + * Check file format etc. for consistency and throw exception if there + * is a problem. + * + * @throws std::runtime_error + */ + void check() const { + if (m_file_format == file_format::unknown) { + std::string msg = "Could not detect file format"; + if (!m_format_string.empty()) { + msg += " from format string '"; + msg += m_format_string; + msg += "'"; + } + if (m_filename.empty()) { + msg += " for stdin/stdout"; + } else { + msg += " for filename '"; + msg += m_filename; + msg += "'"; + } + msg += "."; + throw std::runtime_error(msg); + } + } + + /** + * Set default settings for type and encoding when the filename is + * empty or "-". If you want to have a different default setting + * override this in a subclass. + */ + void default_settings_for_stdinout() { + m_file_format = file_format::unknown; + m_file_compression = file_compression::none; + } + + /** + * Set default settings for type and encoding when the filename is + * a normal file. If you want to have a different default setting + * override this in a subclass. + */ + void default_settings_for_file() { + m_file_format = file_format::unknown; + m_file_compression = file_compression::none; + } + + /** + * Set default settings for type and encoding when the filename is a URL. + * If you want to have a different default setting override this in a + * subclass. + */ + void default_settings_for_url() { + m_file_format = file_format::xml; + m_file_compression = file_compression::none; + } + + file_format format() const { + return m_file_format; + } + + File& format(file_format format) { + m_file_format = format; + return *this; + } + + file_compression compression() const { + return m_file_compression; + } + + File& compression(file_compression compression) { + m_file_compression = compression; + return *this; + } + + bool has_multiple_object_versions() const { + return m_has_multiple_object_versions; + } + + File& has_multiple_object_versions(bool value) { + m_has_multiple_object_versions = value; + return *this; + } + + File& filename(const std::string& filename) { + if (filename == "-") { + m_filename = ""; + } else { + m_filename = filename; + } + return *this; + } + + const std::string& filename() const { + return m_filename; + } + + }; // class File + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_FILE_HPP diff --git a/ThirdParty/osmium/io/file_compression.hpp b/ThirdParty/osmium/io/file_compression.hpp new file mode 100644 index 000000000..8de416d38 --- /dev/null +++ b/ThirdParty/osmium/io/file_compression.hpp @@ -0,0 +1,68 @@ +#ifndef OSMIUM_IO_FILE_COMPRESSION_HPP +#define OSMIUM_IO_FILE_COMPRESSION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +namespace osmium { + + namespace io { + + enum class file_compression { + none = 0, + gzip = 1, + bzip2 = 2 + }; + + inline const char* as_string(file_compression compression) { + switch (compression) { + case file_compression::none: + return "none"; + case file_compression::gzip: + return "gzip"; + case file_compression::bzip2: + return "bzip2"; + } + } + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const file_compression compression) { + return out << as_string(compression); + } + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_FILE_COMPRESSION_HPP diff --git a/ThirdParty/osmium/io/file_format.hpp b/ThirdParty/osmium/io/file_format.hpp new file mode 100644 index 000000000..649e965bf --- /dev/null +++ b/ThirdParty/osmium/io/file_format.hpp @@ -0,0 +1,74 @@ +#ifndef OSMIUM_IO_FILE_FORMAT_HPP +#define OSMIUM_IO_FILE_FORMAT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +namespace osmium { + + namespace io { + + enum class file_format { + unknown = 0, + xml = 1, + pbf = 2, + opl = 3, + json = 4 + }; + + inline const char* as_string(file_format format) { + switch (format) { + case file_format::unknown: + return "unknown"; + case file_format::xml: + return "XML"; + case file_format::pbf: + return "PBF"; + case file_format::opl: + return "OPL"; + case file_format::json: + return "JSON"; + } + } + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const file_format format) { + return out << as_string(format); + } + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_FILE_FORMAT_HPP diff --git a/ThirdParty/osmium/io/gzip_compression.hpp b/ThirdParty/osmium/io/gzip_compression.hpp new file mode 100644 index 000000000..f9afed06c --- /dev/null +++ b/ThirdParty/osmium/io/gzip_compression.hpp @@ -0,0 +1,132 @@ +#ifndef OSMIUM_IO_GZIP_COMPRESSION_HPP +#define OSMIUM_IO_GZIP_COMPRESSION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#define OSMIUM_LINK_WITH_LIBS_ZLIB -lz + +#include +#include + +#include + +#include +#include + +namespace osmium { + + namespace io { + + class GzipCompressor : public Compressor { + + gzFile m_gzfile; + + public: + + explicit GzipCompressor(int fd) : + Compressor(), + m_gzfile(::gzdopen(fd, "w")) { + if (!m_gzfile) { + throw std::runtime_error("initialization of gzip compression failed"); + } + } + + ~GzipCompressor() override final { + this->close(); + } + + void write(const std::string& data) override final { + ::gzwrite(m_gzfile, data.data(), data.size()); + } + + void close() override final { + if (m_gzfile) { + ::gzclose(m_gzfile); + m_gzfile = nullptr; + } + } + + }; // class GzipCompressor + + class GzipDecompressor : public Decompressor { + + gzFile m_gzfile; + + public: + + explicit GzipDecompressor(int fd) : + Decompressor(), + m_gzfile(::gzdopen(fd, "r")) { + if (!m_gzfile) { + throw std::runtime_error("initialization of gzip compression failed"); + } + } + + ~GzipDecompressor() override final { + this->close(); + } + + std::string read() override final { + std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0'); + int nread = ::gzread(m_gzfile, const_cast(buffer.data()), buffer.size()); + if (nread < 0) { + throw std::runtime_error("gzip read failed"); // XXX better error detection and reporting +// throw std::system_error(errno, std::system_category(), "Read failed"); + } + buffer.resize(static_cast(nread)); + return buffer; + } + + void close() override final { + if (m_gzfile) { + ::gzclose(m_gzfile); + m_gzfile = nullptr; + } + } + + }; // class GzipDecompressor + + namespace { + + const bool registered_gzip_compression = osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::gzip, + [](int fd) { return new osmium::io::GzipCompressor(fd); }, + [](int fd) { return new osmium::io::GzipDecompressor(fd); } + ); + + } // anonymous namespace + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_GZIP_COMPRESSION_HPP diff --git a/ThirdParty/osmium/io/header.hpp b/ThirdParty/osmium/io/header.hpp new file mode 100644 index 000000000..c3294756a --- /dev/null +++ b/ThirdParty/osmium/io/header.hpp @@ -0,0 +1,122 @@ +#ifndef OSMIUM_IO_HEADER_HPP +#define OSMIUM_IO_HEADER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include +#include + +namespace osmium { + + namespace io { + + /** + * Meta information from the header of an OSM file. + */ + class Header : public osmium::util::Options { + + /// Bounding boxes + std::vector m_boxes; + + /** + * Are there possibly multiple versions of the same object in this stream of objects? + * This is true for history files and for change files, but not for normal OSM files. + */ + bool m_has_multiple_object_versions = false; + + public: + + Header() = default; + + explicit Header(const std::initializer_list& values) : + Options(values) { + } + + Header(const Header&) = default; + Header& operator=(const Header&) = default; + + Header(Header&&) = default; + Header& operator=(Header&&) = default; + + ~Header() = default; + + std::vector& boxes() { + return m_boxes; + } + + const std::vector& boxes() const { + return m_boxes; + } + + Header& boxes(const std::vector& boxes) { + m_boxes = boxes; + return *this; + } + + osmium::Box box() const { + return m_boxes.empty() ? osmium::Box() : m_boxes.front(); + } + + osmium::Box joined_boxes() const { + osmium::Box box; + for (const auto& b : m_boxes) { + box.extend(b.bottom_left()); + box.extend(b.top_right()); + } + return box; + } + + Header& add_box(const osmium::Box& box) { + m_boxes.push_back(box); + return *this; + } + + bool has_multiple_object_versions() const { + return m_has_multiple_object_versions; + } + + Header& has_multiple_object_versions(bool h) { + m_has_multiple_object_versions = h; + return *this; + } + + }; // class Header + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_HEADER_HPP diff --git a/ThirdParty/osmium/io/input_iterator.hpp b/ThirdParty/osmium/io/input_iterator.hpp new file mode 100644 index 000000000..06be82dc4 --- /dev/null +++ b/ThirdParty/osmium/io/input_iterator.hpp @@ -0,0 +1,139 @@ +#ifndef OSMIUM_IO_INPUT_ITERATOR_HPP +#define OSMIUM_IO_INPUT_ITERATOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace io { + + /** + * This iterator class allows you to iterate over all items from a + * source. It hides all the buffer handling and makes the contents of a + * source accessible as a normal STL input iterator. + */ + template + class InputIterator { + + static_assert(std::is_base_of::value, "TItem must derive from osmium::buffer::Item"); + + typedef typename osmium::memory::Buffer::t_iterator item_iterator; + + TSource* m_source; + std::shared_ptr m_buffer; + item_iterator m_iter {}; + + void update_buffer() { + do { + m_buffer = std::make_shared(std::move(m_source->read())); + if (!m_buffer || !*m_buffer) { // end of input + m_source = nullptr; + m_buffer.reset(); + m_iter = item_iterator(); + return; + } + m_iter = m_buffer->begin(); + } while (m_iter == m_buffer->end()); + } + + public: + + typedef std::input_iterator_tag iterator_category; + typedef TItem value_type; + typedef ptrdiff_t difference_type; + typedef TItem* pointer; + typedef TItem& reference; + + explicit InputIterator(TSource& source) : + m_source(&source) { + update_buffer(); + } + + // end iterator + InputIterator() : + m_source(nullptr) { + } + + InputIterator& operator++() { + assert(m_source); + assert(m_buffer); + assert(m_iter); + ++m_iter; + if (m_iter == m_buffer->end()) { + update_buffer(); + } + return *this; + } + + InputIterator operator++(int) { + InputIterator tmp(*this); + operator++(); + return tmp; + } + + bool operator==(const InputIterator& rhs) const { + return m_source == rhs.m_source && + m_buffer == rhs.m_buffer && + m_iter == rhs.m_iter; + } + + bool operator!=(const InputIterator& rhs) const { + return !(*this == rhs); + } + + reference operator*() const { + assert(m_iter); + return static_cast(*m_iter); + } + + pointer operator->() const { + assert(m_iter); + return &static_cast(*m_iter); + } + + }; // class InputIterator + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_INPUT_ITERATOR_HPP diff --git a/ThirdParty/osmium/io/opl_output.hpp b/ThirdParty/osmium/io/opl_output.hpp new file mode 100644 index 000000000..46a12240b --- /dev/null +++ b/ThirdParty/osmium/io/opl_output.hpp @@ -0,0 +1,39 @@ +#ifndef OSMIUM_IO_OPL_OUTPUT_HPP +#define OSMIUM_IO_OPL_OUTPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_OPL_OUTPUT_HPP diff --git a/ThirdParty/osmium/io/output_iterator.hpp b/ThirdParty/osmium/io/output_iterator.hpp new file mode 100644 index 000000000..d83b10c54 --- /dev/null +++ b/ThirdParty/osmium/io/output_iterator.hpp @@ -0,0 +1,114 @@ +#ifndef OSMIUM_IO_OUTPUT_ITERATOR_HPP +#define OSMIUM_IO_OUTPUT_ITERATOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + namespace memory { + class Item; + } // namespace memory + + namespace io { + + template + class OutputIterator : public std::iterator { + + struct buffer_wrapper { + osmium::memory::Buffer buffer; + + buffer_wrapper(size_t buffer_size) : + buffer(buffer_size, osmium::memory::Buffer::auto_grow::no) { + } + }; + + static constexpr size_t default_buffer_size = 10 * 1024 * 1024; + + TDest& m_destination; + + std::shared_ptr m_buffer_wrapper; + + public: + + explicit OutputIterator(TDest& destination, const size_t buffer_size = default_buffer_size) : + m_destination(destination), + m_buffer_wrapper(std::make_shared(buffer_size)) { + } + + void flush() { + osmium::memory::Buffer buffer(m_buffer_wrapper->buffer.capacity(), osmium::memory::Buffer::auto_grow::no); + std::swap(m_buffer_wrapper->buffer, buffer); + m_destination(std::move(buffer)); + } + + OutputIterator& operator=(const osmium::memory::Item& item) { + try { + m_buffer_wrapper->buffer.push_back(item); + } catch (osmium::memory::BufferIsFull&) { + flush(); + m_buffer_wrapper->buffer.push_back(item); + } + return *this; + } + + OutputIterator& operator=(const osmium::DiffObject& diff) { + return this->operator=(diff.curr()); + } + + OutputIterator& operator*() { + return *this; + } + + OutputIterator& operator++() { + return *this; + } + + OutputIterator& operator++(int) { + return *this; + } + + }; // class OutputIterator + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_OUTPUT_ITERATOR_HPP diff --git a/ThirdParty/osmium/io/overwrite.hpp b/ThirdParty/osmium/io/overwrite.hpp new file mode 100644 index 000000000..e6f1f968f --- /dev/null +++ b/ThirdParty/osmium/io/overwrite.hpp @@ -0,0 +1,52 @@ +#ifndef OSMIUM_IO_OVERWRITE_HPP +#define OSMIUM_IO_OVERWRITE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +namespace osmium { + + namespace io { + + /** + * Allow overwriting of existing file. + */ + enum class overwrite : bool { + no = false, + allow = true + }; + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_OVERWRITE_HPP diff --git a/ThirdParty/osmium/io/pbf_input.hpp b/ThirdParty/osmium/io/pbf_input.hpp new file mode 100644 index 000000000..8426f6cf6 --- /dev/null +++ b/ThirdParty/osmium/io/pbf_input.hpp @@ -0,0 +1,39 @@ +#ifndef OSMIUM_IO_PBF_INPUT_HPP +#define OSMIUM_IO_PBF_INPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_PBF_INPUT_HPP diff --git a/ThirdParty/osmium/io/pbf_output.hpp b/ThirdParty/osmium/io/pbf_output.hpp new file mode 100644 index 000000000..9fd039654 --- /dev/null +++ b/ThirdParty/osmium/io/pbf_output.hpp @@ -0,0 +1,39 @@ +#ifndef OSMIUM_IO_PBF_OUTPUT_HPP +#define OSMIUM_IO_PBF_OUTPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_PBF_OUTPUT_HPP diff --git a/ThirdParty/osmium/io/reader.hpp b/ThirdParty/osmium/io/reader.hpp new file mode 100644 index 000000000..8acac94b5 --- /dev/null +++ b/ThirdParty/osmium/io/reader.hpp @@ -0,0 +1,281 @@ +#ifndef OSMIUM_IO_READER_HPP +#define OSMIUM_IO_READER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _WIN32 +#include +#endif +#ifndef _MSC_VER +#include +#else +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace io { + + /** + * This is the user-facing interface for reading OSM files. Instantiate + * an object of this class with a file name or osmium::io::File object + * and then call read() on it in a loop until it returns an invalid + * Buffer. + */ + class Reader { + + osmium::io::File m_file; + osmium::osm_entity_bits::type m_read_which_entities; + std::atomic m_input_done; + int m_childpid; + + osmium::thread::Queue m_input_queue; + + std::unique_ptr m_decompressor; + osmium::thread::CheckedTask m_read_task; + + std::unique_ptr m_input; + +#ifndef _WIN32 + /** + * Fork and execute the given command in the child. + * A pipe is created between the child and the parent. + * The child writes to the pipe, the parent reads from it. + * This function never returns in the child. + * + * @param command Command to execute in the child. + * @param filename Filename to give to command as argument. + * @return File descriptor of pipe in the parent. + * @throws std::system_error if a system call fails. + */ + static int execute(const std::string& command, const std::string& filename, int* childpid) { + int pipefd[2]; + if (pipe(pipefd) < 0) { + throw std::system_error(errno, std::system_category(), "opening pipe failed"); + } + pid_t pid = fork(); + if (pid < 0) { + throw std::system_error(errno, std::system_category(), "fork failed"); + } + if (pid == 0) { // child + // close all file descriptors except one end of the pipe + for (int i=0; i < 32; ++i) { + if (i != pipefd[1]) { + ::close(i); + } + } + if (dup2(pipefd[1], 1) < 0) { // put end of pipe as stdout/stdin + exit(1); + } + + ::open("/dev/null", O_RDONLY); // stdin + ::open("/dev/null", O_WRONLY); // stderr + // hack: -g switches off globbing in curl which allows [] to be used in file names + // this is important for XAPI URLs + // in theory this execute() function could be used for other commands, but it is + // only used for curl at the moment, so this is okay. + if (::execlp(command.c_str(), command.c_str(), "-g", filename.c_str(), nullptr) < 0) { + exit(1); + } + } + // parent + *childpid = pid; + ::close(pipefd[1]); + return pipefd[0]; + } +#endif + + /** + * Open File for reading. Handles URLs or normal files. URLs + * are opened by executing the "curl" program (which must be installed) + * and reading from its output. + * + * @return File descriptor of open file or pipe. + * @throws std::system_error if a system call fails. + */ + static int open_input_file_or_url(const std::string& filename, int* childpid) { + std::string protocol = filename.substr(0, filename.find_first_of(':')); + if (protocol == "http" || protocol == "https" || protocol == "ftp" || protocol == "file") { +#ifndef _WIN32 + return execute("curl", filename, childpid); +#else + throw std::runtime_error("Reading OSM files from the network currently not supported on Windows."); +#endif + } else { + return osmium::io::detail::open_for_reading(filename); + } + } + + public: + + /** + * Create new Reader object. + * + * @param file The file we want to open. + * @param read_which_entities Which OSM entities (nodes, ways, relations, and/or changesets) + * should be read from the input file. It can speed the read up + * significantly if objects that are not needed anyway are not + * parsed. + */ + explicit Reader(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities = osmium::osm_entity_bits::all) : + m_file(file), + m_read_which_entities(read_which_entities), + m_input_done(false), + m_childpid(0), + m_input_queue(), + m_decompressor(osmium::io::CompressionFactory::instance().create_decompressor(file.compression(), open_input_file_or_url(m_file.filename(), &m_childpid))), + m_read_task(m_input_queue, m_decompressor.get(), m_input_done), + m_input(osmium::io::detail::InputFormatFactory::instance().create_input(m_file, m_read_which_entities, m_input_queue)) { + } + + explicit Reader(const std::string& filename, osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all) : + Reader(osmium::io::File(filename), read_types) { + } + + explicit Reader(const char* filename, osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all) : + Reader(osmium::io::File(filename), read_types) { + } + + Reader(const Reader&) = delete; + Reader& operator=(const Reader&) = delete; + + ~Reader() { + close(); + } + + /** + * Close down the Reader. A call to this is optional, because the + * destructor of Reader will also call this. But if you don't call + * this function first, the destructor might throw an exception + * which is not good. + * + * @throws Some form of std::runtime_error when there is a problem. + */ + void close() { + // Signal to input child process that it should wrap up. + m_input_done = true; + + m_input->close(); + +#ifndef _WIN32 + if (m_childpid) { + int status; + pid_t pid = ::waitpid(m_childpid, &status, 0); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" + if (pid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { + throw std::system_error(errno, std::system_category(), "subprocess returned error"); + } +#pragma GCC diagnostic pop + m_childpid = 0; + } +#endif + + m_read_task.close(); + } + + /** + * Get the header data from the file. + */ + osmium::io::Header header() const { + return m_input->header(); + } + + /** + * Reads the next buffer from the input. An invalid buffer signals + * end-of-file. Do not call read() after the end-of-file. + * + * @returns Buffer. + * @throws Some form of std::runtime_error if there is an error. + */ + osmium::memory::Buffer read() { + // If an exception happened in the input thread, re-throw + // it in this (the main) thread. + m_read_task.check_for_exception(); + + if (m_read_which_entities == osmium::osm_entity_bits::nothing) { + // If the caller didn't want anything but the header, it will + // always get an empty buffer here. + return osmium::memory::Buffer(); + } + return m_input->read(); + } + + }; // class Reader + + /** + * Read contents of the given file into a buffer in one go. Takes + * the same arguments as any of the Reader constructors. + * + * The buffer can take up quite a lot of memory, so don't do this + * unless you are working with small OSM files and/or have lots of + * RAM. + */ + template + osmium::memory::Buffer read_file(TArgs&&... args) { + osmium::memory::Buffer buffer(1024*1024, osmium::memory::Buffer::auto_grow::yes); + + Reader reader(std::forward(args)...); + while (osmium::memory::Buffer read_buffer = reader.read()) { + buffer.add_buffer(read_buffer); + buffer.commit(); + } + + return buffer; + } + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_READER_HPP diff --git a/ThirdParty/osmium/io/reader_iterator.hpp b/ThirdParty/osmium/io/reader_iterator.hpp new file mode 100644 index 000000000..ee5cc5b51 --- /dev/null +++ b/ThirdParty/osmium/io/reader_iterator.hpp @@ -0,0 +1,51 @@ +#ifndef OSMIUM_IO_READER_ITERATOR_HPP +#define OSMIUM_IO_READER_ITERATOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +namespace std { + + inline osmium::io::InputIterator begin(osmium::io::Reader& reader) { + return osmium::io::InputIterator(reader); + } + + inline osmium::io::InputIterator end(osmium::io::Reader&) { + return osmium::io::InputIterator(); + } + +} // namespace std + +#endif // OSMIUM_IO_READER_ITERATOR_HPP diff --git a/ThirdParty/osmium/io/writer.hpp b/ThirdParty/osmium/io/writer.hpp new file mode 100644 index 000000000..c5ff05cf2 --- /dev/null +++ b/ThirdParty/osmium/io/writer.hpp @@ -0,0 +1,142 @@ +#ifndef OSMIUM_IO_WRITER_HPP +#define OSMIUM_IO_WRITER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace io { + + /** + * This is the user-facing interface for writing OSM files. Instantiate + * an object of this class with a file name or osmium::io::File object + * and optionally the data for the header and then call operator() on it + * to write Buffers. Call close() to finish up. + */ + class Writer { + + osmium::io::File m_file; + + std::unique_ptr m_output; + osmium::io::detail::data_queue_type m_output_queue; + + std::unique_ptr m_compressor; + + osmium::thread::CheckedTask m_write_task; + + public: + + /** + * The constructor of the Writer object opens a file and writes the + * header to it. + * + * @param file File (contains name and format info) to open. + * @param header Optional header data. If this is not given sensible + * defaults will be used. See the default constructor + * of osmium::io::Header for details. + * @param allow_overwrite Allow overwriting of existing file? Can be + * osmium::io::overwrite::allow or osmium::io::overwrite::no+ + * (default). + * + * @throws std::runtime_error If the file could not be opened. + * @throws std::system_error If the file could not be opened. + */ + explicit Writer(const osmium::io::File& file, const osmium::io::Header& header = osmium::io::Header(), overwrite allow_overwrite = overwrite::no) : + m_file(file), + m_output(osmium::io::detail::OutputFormatFactory::instance().create_output(m_file, m_output_queue)), + m_compressor(osmium::io::CompressionFactory::instance().create_compressor(file.compression(), osmium::io::detail::open_for_writing(m_file.filename(), allow_overwrite))), + m_write_task(m_output_queue, m_compressor.get()) { + m_output->write_header(header); + } + + explicit Writer(const std::string& filename, const osmium::io::Header& header = osmium::io::Header(), overwrite allow_overwrite = overwrite::no) : + Writer(osmium::io::File(filename), header, allow_overwrite) { + } + + explicit Writer(const char* filename, const osmium::io::Header& header = osmium::io::Header(), overwrite allow_overwrite = overwrite::no) : + Writer(osmium::io::File(filename), header, allow_overwrite) { + } + + Writer(const Writer&) = delete; + Writer& operator=(const Writer&) = delete; + + ~Writer() { + close(); + } + + /** + * Write contents of a buffer to the output file. + * + * @throws Some form of std::runtime_error when there is a problem. + */ + void operator()(osmium::memory::Buffer&& buffer) { + m_write_task.check_for_exception(); + if (buffer.committed() > 0) { + m_output->write_buffer(std::move(buffer)); + } + } + + /** + * Flush writes to output file and close it. If you do not + * call this, the destructor of Writer will also do the same + * thing. But because this call might thrown an exception, + * it is better to call close() explicitly. + * + * @throws Some form of std::runtime_error when there is a problem. + */ + void close() { + m_output->close(); + m_write_task.close(); + } + + }; // class Writer + + } // namespace io + +} // namespace osmium + +#endif // OSMIUM_IO_WRITER_HPP diff --git a/ThirdParty/osmium/io/xml_input.hpp b/ThirdParty/osmium/io/xml_input.hpp new file mode 100644 index 000000000..f33d37ee2 --- /dev/null +++ b/ThirdParty/osmium/io/xml_input.hpp @@ -0,0 +1,39 @@ +#ifndef OSMIUM_IO_XML_INPUT_HPP +#define OSMIUM_IO_XML_INPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_XML_INPUT_HPP diff --git a/ThirdParty/osmium/io/xml_output.hpp b/ThirdParty/osmium/io/xml_output.hpp new file mode 100644 index 000000000..d5b839f60 --- /dev/null +++ b/ThirdParty/osmium/io/xml_output.hpp @@ -0,0 +1,39 @@ +#ifndef OSMIUM_IO_XML_OUTPUT_HPP +#define OSMIUM_IO_XML_OUTPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include // IWYU pragma: export +#include // IWYU pragma: export + +#endif // OSMIUM_IO_XML_OUTPUT_HPP diff --git a/ThirdParty/osmium/memory/buffer.hpp b/ThirdParty/osmium/memory/buffer.hpp new file mode 100644 index 000000000..a8a9c7441 --- /dev/null +++ b/ThirdParty/osmium/memory/buffer.hpp @@ -0,0 +1,523 @@ +#ifndef OSMIUM_MEMORY_BUFFER_HPP +#define OSMIUM_MEMORY_BUFFER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace osmium { + + /** + * @brief Memory management of items in buffers and iterators over this data. + */ + namespace memory { + + /** + * Exception thrown by the Buffer class when somebody tries to write data + * into the buffer and it doesn't fit. + */ + class BufferIsFull : public std::exception {}; + + /** + * A memory area for storing OSM objects and other items. Each item stored + * has a type and a length. See the Item class for details. + * + * Data can be added to a buffer piece by piece using reserve_space() and + * add_item(). After all data that together forms an item is added, it must + * be committed using the commit() call. Usually this is done through the + * Builder class and its derived classes. + * + * You can iterate over all items in a buffer using the iterators returned + * by begin(), end(), cbegin(), and cend(). + * + * Buffers exist in two flavours, those with external memory management and + * those with internal memory management. If you already have some memory + * with data in it (for instance read from disk), you create a Buffer with + * external memory managment. It is your job then to free the memory once + * the buffer isn't used any more. If you don't have memory already, you can + * create a Buffer object and have it manage the memory internally. It will + * dynamically allocate memory and free it again after use. + * + * By default, if a buffer gets full it will throw a BufferIsFull exception. + * You can use the set_full_callback() method to set a callback functor + * which will be called instead of throwing an exception. + */ + class Buffer { + + public: + + enum class auto_grow : bool { + yes = true, + no = false + }; + + private: + + std::vector m_memory; + unsigned char* m_data; + size_t m_capacity; + size_t m_written; + size_t m_committed; + auto_grow m_auto_grow {auto_grow::no}; + std::function m_full; + + public: + + typedef Item value_type; + + /** + * The constructor without any parameters creates a non-initialized + * buffer, ie an empty hull of a buffer that has no actual memory + * associated with it. It can be used to signify end-of-input. + */ + Buffer() : + m_memory(), + m_data(nullptr), + m_capacity(0), + m_written(0), + m_committed(0) { + } + + /** + * Constructs an externally memory-managed buffer using the given + * memory and size. + * + * @param data A pointer to some already initialized data. + * @param size The size of the initialized data. + * @exception std::invalid_argument When the size isn't a multiple of the alignment. + */ + explicit Buffer(unsigned char* data, size_t size) : + m_memory(), + m_data(data), + m_capacity(size), + m_written(size), + m_committed(size) { + if (size % align_bytes != 0) { + throw std::invalid_argument("buffer size needs to be multiple of alignment"); + } + } + + /** + * Constructs an externally memory-managed buffer with the given + * capacity that already contains 'committed' bytes of data. + * + * @param data A pointer to some (possibly initialized) data. + * @param capacity The size of the memory for this buffer. + * @param committed The size of the initialized data. If this is 0, the buffer startes out empty. + * @exception std::invalid_argument When the capacity or committed isn't a multiple of the alignment. + */ + explicit Buffer(unsigned char* data, size_t capacity, size_t committed) : + m_memory(), + m_data(data), + m_capacity(capacity), + m_written(committed), + m_committed(committed) { + if (capacity % align_bytes != 0) { + throw std::invalid_argument("buffer capacity needs to be multiple of alignment"); + } + if (committed % align_bytes != 0) { + throw std::invalid_argument("buffer parameter 'committed' needs to be multiple of alignment"); + } + } + + /** + * Create an internally memory-managed buffer with the given capacity. + * different in that it internally gets dynamic memory of the + * required size. The dynamic memory will be automatically + * freed when the Buffer is destroyed. + */ + explicit Buffer(size_t capacity, auto_grow auto_grow = auto_grow::yes) : + m_memory(capacity), + m_data(m_memory.data()), + m_capacity(capacity), + m_written(0), + m_committed(0), + m_auto_grow(auto_grow) { + if (capacity % align_bytes != 0) { + throw std::invalid_argument("buffer capacity needs to be multiple of alignment"); + } + } + + // buffers can not be copied + Buffer(const Buffer&) = delete; + Buffer& operator=(const Buffer&) = delete; + + // buffers can be moved + Buffer(Buffer&&) = default; + Buffer& operator=(Buffer&&) = default; + + ~Buffer() = default; + + /** + * Return a pointer to data inside the buffer. + */ + unsigned char* data() const { + return m_data; + } + + /** + * Returns the capacity of the buffer, ie how many bytes it can contain. + */ + size_t capacity() const { + return m_capacity; + } + + /** + * Returns the number of bytes already filled in this buffer. + */ + size_t committed() const { + return m_committed; + } + + /** + * Returns the number of bytes currently filled in this buffer that + * are not yet committed. + */ + size_t written() const { + return m_written; + } + + /** + * This tests if the current state of the buffer is aligned + * properly. Can be used for asserts. + */ + bool is_aligned() const { + return (m_written % align_bytes == 0) && (m_committed % align_bytes == 0); + } + + /** + * Set functor to be called whenever the buffer is full + * instead of throwing BufferIsFull. + */ + void set_full_callback(std::function full) { + m_full = full; + } + + /** + * Grow capacity of this buffer to the given size. + * This works only with internally memory-managed buffers. + * If the given size is not larger than the current capacity, nothing is done. + * Already written but not committed data is discarded. + * + * @param size New capacity. + */ + void grow(size_t size) { + if (m_memory.empty()) { + throw std::logic_error("Can't grow Buffer if it doesn't use internal memory management."); + } + if (m_capacity < size) { + if (size % align_bytes != 0) { + throw std::invalid_argument("buffer capacity needs to be multiple of alignment"); + } + m_memory.resize(size); + m_data = m_memory.data(); + m_capacity = size; + } + } + + /** + * Mark currently written bytes in the buffer as committed. + * + * @return Last number of committed bytes before this commit. + */ + size_t commit() { + assert(is_aligned()); + + const size_t offset = m_committed; + m_committed = m_written; + return offset; + } + + /** + * Roll back changes in buffer to last committed state. + */ + void rollback() { + m_written = m_committed; + } + + /** + * Clear the buffer. + * + * @return Number of bytes in the buffer before it was cleared. + */ + size_t clear() { + const size_t committed = m_committed; + m_written = 0; + m_committed = 0; + return committed; + } + + /** + * Get the data in the buffer at the given offset. + * + * @tparam T Type we want to the data to be interpreted as. + * @return Reference of given type pointing to the data in the buffer. + */ + template + T& get(const size_t offset) const { + return *reinterpret_cast(&m_data[offset]); + } + + /** + * Reserve space of given size in buffer and return pointer to it. + * This is the only way of adding data to the buffer. You reserve + * the space and then fill it. + * + * Note that you have to eventually call commit() to actually + * commit this data. + * + * If there isn't enough space in the buffer, one of three things + * can happen: + * + * * If you have set a callback with set_full_callback(), it is + * called. After the call returns, you must have either grown + * the buffer or cleared it by calling buffer.clear(). + * * If no callback is defined and this buffer uses internal + * memory management, the buffers capacity is grown, so that + * the new data will fit. + * * Else the BufferIsFull exception is thrown. + * + * @param size Number of bytes to reserve. + * @return Pointer to reserved space. Note that this pointer is + * only guaranteed to be valid until the next call to + * reserve_space(). + * @throw BufferIsFull Might be thrown if the buffer is full. + */ + unsigned char* reserve_space(const size_t size) { + if (m_written + size > m_capacity) { + if (m_full) { + m_full(*this); + } else if (!m_memory.empty() && (m_auto_grow == auto_grow::yes)) { + // double buffer size until there is enough space + size_t new_capacity = m_capacity * 2; + while (m_written + size > new_capacity) { + new_capacity *= 2; + } + grow(new_capacity); + } else { + throw BufferIsFull(); + } + } + unsigned char* data = &m_data[m_written]; + m_written += size; + return data; + } + + /** + * Add an item to the buffer. The size of the item is stored inside + * the item, so we know how much memory to copy. + * + * Note that you have to eventually call commit() to actually + * commit this data. + * + * @tparam T Class of the item to be copied. + * @param item Reference to the item to be copied. + * @return Reference to newly copied data in the buffer. + */ + template + T& add_item(const T& item) { + unsigned char* ptr = reserve_space(item.padded_size()); + std::memcpy(ptr, &item, item.padded_size()); + return *reinterpret_cast(ptr); + } + + /** + * Add committed contents of the given buffer to this buffer. + * + * Note that you have to eventually call commit() to actually + * commit this data. + */ + void add_buffer(const Buffer& buffer) { + unsigned char* ptr = reserve_space(buffer.committed()); + std::memcpy(ptr, buffer.data(), buffer.committed()); + } + + /** + * Add an item to the buffer. This function is provided so that + * you can use std::back_inserter. + */ + void push_back(const osmium::memory::Item& item) { + add_item(item); + commit(); + } + + /** + * These iterators can be used to iterate over all items in + * a buffer. + */ + template + using t_iterator = osmium::memory::ItemIterator; + + template + using t_const_iterator = osmium::memory::ItemIterator; + + typedef t_iterator iterator; + typedef t_const_iterator const_iterator; + + template + t_iterator begin() { + return t_iterator(m_data, m_data + m_committed); + } + + iterator begin() { + return iterator(m_data, m_data + m_committed); + } + + template + t_iterator end() { + return t_iterator(m_data + m_committed, m_data + m_committed); + } + + iterator end() { + return iterator(m_data + m_committed, m_data + m_committed); + } + + template + t_const_iterator cbegin() const { + return t_const_iterator(m_data, m_data + m_committed); + } + + const_iterator cbegin() const { + return const_iterator(m_data, m_data + m_committed); + } + + template + t_const_iterator cend() const { + return t_const_iterator(m_data + m_committed, m_data + m_committed); + } + + const_iterator cend() const { + return const_iterator(m_data + m_committed, m_data + m_committed); + } + + template + t_const_iterator begin() const { + return cbegin(); + } + + const_iterator begin() const { + return cbegin(); + } + + template + t_const_iterator end() const { + return cend(); + } + + const_iterator end() const { + return cend(); + } + + /** + * In a bool context any initialized buffer is true. + */ + explicit operator bool() const { + return m_data != nullptr; + } + + friend void swap(Buffer& lhs, Buffer& rhs) { + using std::swap; + + swap(lhs.m_memory, rhs.m_memory); + swap(lhs.m_data, rhs.m_data); + swap(lhs.m_capacity, rhs.m_capacity); + swap(lhs.m_written, rhs.m_written); + swap(lhs.m_committed, rhs.m_committed); + } + + /** + * Purge removed items from the buffer. This is done by moving all + * non-removed items forward in the buffer overwriting removed + * items and then correcting the m_written and m_committed numbers. + * + * Note that calling this function invalidates all iterators on this + * buffer and all offsets in this buffer. + * + * For every non-removed item that moves its position, the function + * 'moving_in_buffer' is called on the given callback object with + * the old and new offsets in the buffer where the object used to + * be and is now, respectively. This call can be used to update any + * indexes. + */ + template + void purge_removed(TCallbackClass* callback) { + iterator it_write = begin(); + + iterator next; + for (iterator it_read = begin(); it_read != end(); it_read = next) { + next = std::next(it_read); + if (!it_read->removed()) { + if (it_read != it_write) { + assert(it_read->data() >= data()); + assert(it_write->data() >= data()); + size_t old_offset = static_cast(it_read->data() - data()); + size_t new_offset = static_cast(it_write->data() - data()); + callback->moving_in_buffer(old_offset, new_offset); + std::memmove(it_write->data(), it_read->data(), it_read->padded_size()); + } + ++it_write; + } + } + + assert(it_write->data() >= data()); + m_written = static_cast(it_write->data() - data()); + m_committed = m_written; + } + + }; // class Buffer + + inline bool operator==(const Buffer& lhs, const Buffer& rhs) { + return lhs.data() == rhs.data() && lhs.capacity() == rhs.capacity() && lhs.committed() == rhs.committed(); + } + + inline bool operator!=(const Buffer& lhs, const Buffer& rhs) { + return ! (lhs == rhs); + } + + } // namespace memory + +} // namespace osmium + +#endif // OSMIUM_MEMORY_BUFFER_HPP diff --git a/ThirdParty/osmium/memory/collection.hpp b/ThirdParty/osmium/memory/collection.hpp new file mode 100644 index 000000000..c6256b175 --- /dev/null +++ b/ThirdParty/osmium/memory/collection.hpp @@ -0,0 +1,153 @@ +#ifndef OSMIUM_MEMORY_COLLECTION_HPP +#define OSMIUM_MEMORY_COLLECTION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include + +namespace osmium { + + namespace memory { + + template + class CollectionIterator : public std::iterator { + + // This data_type is either 'unsigned char*' or 'const unsigned char*' depending + // on whether TMember is const. This allows this class to be used as an iterator and + // as a const_iterator. + typedef typename std::conditional::value, const unsigned char*, unsigned char*>::type data_type; + + data_type m_data; + + public: + + CollectionIterator() : + m_data(nullptr) { + } + + CollectionIterator(data_type data) : + m_data(data) { + } + + CollectionIterator& operator++() { + m_data = reinterpret_cast(m_data)->next(); + return *static_cast*>(this); + } + + CollectionIterator operator++(int) { + CollectionIterator tmp(*this); + operator++(); + return tmp; + } + + bool operator==(const CollectionIterator& rhs) const { + return m_data == rhs.m_data; + } + + bool operator!=(const CollectionIterator& rhs) const { + return m_data != rhs.m_data; + } + + unsigned char* data() const { + return m_data; + } + + TMember& operator*() const { + return *reinterpret_cast(m_data); + } + + TMember* operator->() const { + return reinterpret_cast(m_data); + } + + template + friend std::basic_ostream& operator<<(std::basic_ostream& out, const CollectionIterator& iter) { + return out << static_cast(iter.m_data); + } + + }; // class CollectionIterator + + template + class Collection : public Item { + + public: + + typedef CollectionIterator iterator; + typedef CollectionIterator const_iterator; + typedef TMember value_type; + + static constexpr osmium::item_type itemtype = TCollectionItemType; + + Collection() : + Item(sizeof(Collection), TCollectionItemType) { + } + + bool empty() const { + return sizeof(Collection) == byte_size(); + } + + iterator begin() { + return iterator(data() + sizeof(Collection)); + } + + iterator end() { + return iterator(data() + byte_size()); + } + + const_iterator cbegin() const { + return const_iterator(data() + sizeof(Collection)); + } + + const_iterator cend() const { + return const_iterator(data() + byte_size()); + } + + const_iterator begin() const { + return cbegin(); + } + + const_iterator end() const { + return cend(); + } + + }; // class Collection + + } // namespace memory + +} // namespace osmium + +#endif // OSMIUM_MEMORY_COLLECTION_HPP diff --git a/ThirdParty/osmium/memory/item.hpp b/ThirdParty/osmium/memory/item.hpp new file mode 100644 index 000000000..73e653efe --- /dev/null +++ b/ThirdParty/osmium/memory/item.hpp @@ -0,0 +1,178 @@ +#ifndef OSMIUM_MEMORY_ITEM_HPP +#define OSMIUM_MEMORY_ITEM_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +namespace osmium { + + // forward declaration, see osmium/osm/item_type.hpp for declaration + enum class item_type : uint16_t; + + namespace builder { + class Builder; + } + + namespace memory { + + typedef uint32_t item_size_type; + + // align datastructures to this many bytes + constexpr item_size_type align_bytes = 8; + + inline size_t padded_length(size_t length) { + return (length + align_bytes - 1) & ~(align_bytes - 1); + } + + inline item_size_type padded_length(item_size_type length) { + return (length + align_bytes - 1) & ~(align_bytes - 1); + } + + /** + * @brief Namespace for Osmium internal use + */ + namespace detail { + + /** + * This class contains only a helper method used in several + * other classes. + */ + class ItemHelper { + + protected: + + ItemHelper() = default; + + ~ItemHelper() = default; + + ItemHelper(const ItemHelper&) = default; + ItemHelper(ItemHelper&&) = default; + + ItemHelper& operator=(const ItemHelper&) = default; + ItemHelper& operator=(ItemHelper&&) = default; + + public: + + unsigned char* data() { + return reinterpret_cast(this); + } + + const unsigned char* data() const { + return reinterpret_cast(this); + } + + }; + + } // namespace detail + + class Item : public osmium::memory::detail::ItemHelper { + + item_size_type m_size; + item_type m_type; + uint16_t m_removed : 1; + uint16_t m_padding : 15; + + template + friend class CollectionIterator; + + template + friend class ItemIterator; + + friend class osmium::builder::Builder; + + unsigned char* next() { + return data() + padded_size(); + } + + const unsigned char* next() const { + return data() + padded_size(); + } + + Item& add_size(const item_size_type size) { + m_size += size; + return *this; + } + + protected: + + explicit Item(item_size_type size=0, item_type type=item_type()) : + m_size(size), + m_type(type), + m_removed(false) { + } + + Item(const Item&) = delete; + Item(Item&&) = delete; + + Item& operator=(const Item&) = delete; + Item& operator=(Item&&) = delete; + + Item& type(const item_type item_type) { + m_type = item_type; + return *this; + } + + public: + + item_size_type byte_size() const { + return m_size; + } + + item_size_type padded_size() const { + return padded_length(m_size); + } + + item_type type() const { + return m_type; + } + + bool removed() const { + return m_removed; + } + + void removed(bool removed) { + m_removed = removed; + } + + }; // class Item + + static_assert(sizeof(Item) == 8, "Class osmium::Item has wrong size!"); + static_assert(sizeof(Item) % align_bytes == 0, "Class osmium::Item has wrong size to be aligned properly!"); + + } // namespace memory + +} // namespace osmium + +#endif // OSMIUM_MEMORY_ITEM_HPP diff --git a/ThirdParty/osmium/memory/item_iterator.hpp b/ThirdParty/osmium/memory/item_iterator.hpp new file mode 100644 index 000000000..64899b333 --- /dev/null +++ b/ThirdParty/osmium/memory/item_iterator.hpp @@ -0,0 +1,181 @@ +#ifndef OSMIUM_ITEM_ITERATOR_HPP +#define OSMIUM_ITEM_ITERATOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +#include +#include +#include + +namespace osmium { + + namespace memory { + + namespace detail { + + template + inline bool type_is_compatible(osmium::item_type) { + return true; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) { + return t == osmium::item_type::node; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) { + return t == osmium::item_type::way; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) { + return t == osmium::item_type::relation; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) { + return t == osmium::item_type::area; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) { + return t == osmium::item_type::changeset; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) { + return t == osmium::item_type::node || t == osmium::item_type::way || t == osmium::item_type::relation || t == osmium::item_type::area; + } + + template <> + inline bool type_is_compatible(osmium::item_type t) { + return t == osmium::item_type::node || t == osmium::item_type::way || t == osmium::item_type::relation || t == osmium::item_type::area || t == osmium::item_type::changeset; + } + + } // namespace detail + + template + class ItemIterator : public std::iterator { + + static_assert(std::is_base_of::value, "TMember must derive from osmium::memory::Item"); + + // This data_type is either 'unsigned char*' or 'const unsigned char*' depending + // on whether TMember is const. This allows this class to be used as an iterator and + // as a const_iterator. + typedef typename std::conditional::value, const unsigned char*, unsigned char*>::type data_type; + + data_type m_data; + data_type m_end; + + void advance_to_next_item_of_right_type() { + while (m_data != m_end && + !detail::type_is_compatible::type>(reinterpret_cast(m_data)->type())) { + m_data = reinterpret_cast(m_data)->next(); + } + } + + public: + + ItemIterator() : + m_data(nullptr), + m_end(nullptr) { + } + + ItemIterator(data_type data, data_type end) : + m_data(data), + m_end(end) { + advance_to_next_item_of_right_type(); + } + + ItemIterator& operator++() { + assert(m_data); + assert(m_data != m_end); + m_data = reinterpret_cast(m_data)->next(); + advance_to_next_item_of_right_type(); + return *static_cast*>(this); + } + + ItemIterator operator++(int) { + ItemIterator tmp(*this); + operator++(); + return tmp; + } + + bool operator==(const ItemIterator& rhs) const { + return m_data == rhs.m_data && m_end == rhs.m_end; + } + + bool operator!=(const ItemIterator& rhs) const { + return !(*this == rhs); + } + + unsigned char* data() const { + assert(m_data); + assert(m_data != m_end); + return m_data; + } + + TMember& operator*() const { + assert(m_data); + assert(m_data != m_end); + return *reinterpret_cast(m_data); + } + + TMember* operator->() const { + assert(m_data); + assert(m_data != m_end); + return reinterpret_cast(m_data); + } + + explicit operator bool() const { + return m_data != nullptr; + } + + template + friend std::basic_ostream& operator<<(std::basic_ostream& out, const ItemIterator& iter) { + return out << static_cast(iter.m_data); + } + + }; // class ItemIterator + + } // namespace memory + +} // namespace osmium + +#endif // OSMIUM_ITEM_ITERATOR_HPP diff --git a/ThirdParty/osmium/object_pointer_collection.hpp b/ThirdParty/osmium/object_pointer_collection.hpp new file mode 100644 index 000000000..08ea46e01 --- /dev/null +++ b/ThirdParty/osmium/object_pointer_collection.hpp @@ -0,0 +1,112 @@ +#ifndef OSMIUM_OBJECT_POINTER_COLLECTION_HPP +#define OSMIUM_OBJECT_POINTER_COLLECTION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include + +#include +#include +#include + +// IWYU pragma: no_forward_declare osmium::OSMObject +// IWYU pragma: no_forward_declare osmium::memory::Item + +namespace osmium { + + /** + * A collection of pointers to OSM objects. The pointers can be easily + * and quickly sorted or otherwise manipulated, while the objects + * themselves or the buffers they are in, do not have to be changed. + * + * An iterator is provided that can iterate over the pointers but looks + * like it is iterating over the underlying OSM objects. + * + * This class implements the visitor pattern which makes it easy to + * populate the collection from a buffer of OSM objects: + * + * osmium::ObjectPointerCollection objects; + * osmium::memory::Buffer buffer = reader.read(); + * osmium::apply(buffer, objects); + * + */ + class ObjectPointerCollection : public osmium::handler::Handler { + + std::vector m_objects; + + public: + + typedef boost::indirect_iterator::iterator, osmium::OSMObject> iterator; + typedef boost::indirect_iterator::const_iterator, const osmium::OSMObject> const_iterator; + + ObjectPointerCollection() : + m_objects() { + } + + void osm_object(osmium::OSMObject& object) { + m_objects.push_back(&object); + } + + /** + * Sort objects according to the given order functor. + */ + template + void sort(TCompare&& compare) { + std::sort(m_objects.begin(), m_objects.end(), std::forward(compare)); + } + + iterator begin() { + return iterator { m_objects.begin() }; + } + + iterator end() { + return iterator { m_objects.end() }; + } + + const_iterator cbegin() const { + return const_iterator { m_objects.cbegin() }; + } + + const_iterator cend() const { + return const_iterator { m_objects.cend() }; + } + + }; // class ObjectPointerCollection + +} // namespace osmium + +#endif // OSMIUM_OBJECT_POINTER_COLLECTION_HPP diff --git a/ThirdParty/osmium/osm.hpp b/ThirdParty/osmium/osm.hpp new file mode 100644 index 000000000..9f5c162f0 --- /dev/null +++ b/ThirdParty/osmium/osm.hpp @@ -0,0 +1,48 @@ +#ifndef OSMIUM_OSM_HPP +#define OSMIUM_OSM_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export + +/** + * @brief Namespace for everything in the Osmium library. + */ +namespace osmium { +} // namespace osmium + +#endif // OSMIUM_OSM_HPP diff --git a/ThirdParty/osmium/osm/area.hpp b/ThirdParty/osmium/osm/area.hpp new file mode 100644 index 000000000..5d8233de9 --- /dev/null +++ b/ThirdParty/osmium/osm/area.hpp @@ -0,0 +1,172 @@ +#ifndef OSMIUM_OSM_AREA_HPP +#define OSMIUM_OSM_AREA_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace builder { + template class ObjectBuilder; + } + + /** + * An outer ring of an Area. + */ + class OuterRing : public NodeRefList { + + public: + + OuterRing(): + NodeRefList() { + } + + }; // class OuterRing + + static_assert(sizeof(OuterRing) % osmium::memory::align_bytes == 0, "Class osmium::OuterRing has wrong size to be aligned properly!"); + + /** + * An inner ring of an Area. + */ + class InnerRing : public NodeRefList { + + public: + + InnerRing(): + NodeRefList() { + } + + }; // class InnerRing + + static_assert(sizeof(InnerRing) % osmium::memory::align_bytes == 0, "Class osmium::InnerRing has wrong size to be aligned properly!"); + + /** + * Convert way or (multipolygon) relation id into unique area id. + * + * @param id Id of a way or relation + * @param type Type of object (way or relation) + * @returns Area id + */ + inline osmium::object_id_type object_id_to_area_id(osmium::object_id_type id, osmium::item_type type) { + osmium::object_id_type area_id = std::abs(id) * 2; + if (type == osmium::item_type::relation) { + ++area_id; + } + return id < 0 ? -area_id : area_id; + } + + /** + * Convert area id into id of the way or relation it was created from. + * + * @param id Area id + * @returns Way or Relation id. + */ + inline osmium::object_id_type area_id_to_object_id(osmium::object_id_type id) { + return id / 2; + } + + /** + * An OSM area created out of a closed way or a multipolygon relation. + */ + class Area : public OSMObject { + + friend class osmium::builder::ObjectBuilder; + + Area() : + OSMObject(sizeof(Area), osmium::item_type::area) { + } + + public: + + static constexpr osmium::item_type itemtype = osmium::item_type::area; + + /** + * Was this area created from a way? (In contrast to areas + * created from a relation and their members.) + */ + bool from_way() const { + return (positive_id() & 0x1) == 0; + } + + /** + * Return the Id of the way or relation this area was created from. + */ + osmium::object_id_type orig_id() const { + return osmium::area_id_to_object_id(id()); + } + + /** + * Count the number of outer and inner rings of this area. + */ + std::pair num_rings() const { + std::pair counter; + + for (auto it = cbegin(); it != cend(); ++it) { + switch (it->type()) { + case osmium::item_type::outer_ring: + ++counter.first; + break; + case osmium::item_type::inner_ring: + ++counter.second; + break; + default: + break; + } + } + + return counter; + } + + /** + * Is this area a multipolygon, ie. has it more than one outer ring? + */ + bool is_multipolygon() const { + return num_rings().first > 1; + } + + }; // class Area + + static_assert(sizeof(Area) % osmium::memory::align_bytes == 0, "Class osmium::Area has wrong size to be aligned properly!"); + +} // namespace osmium + +#endif // OSMIUM_OSM_AREA_HPP diff --git a/ThirdParty/osmium/osm/box.hpp b/ThirdParty/osmium/osm/box.hpp new file mode 100644 index 000000000..fea0c70cd --- /dev/null +++ b/ThirdParty/osmium/osm/box.hpp @@ -0,0 +1,207 @@ +#ifndef OSMIUM_OSM_BOX_HPP +#define OSMIUM_OSM_BOX_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +#include +#include + +namespace osmium { + + /** + * Bounding box. + */ + class Box { + + osmium::Location m_bottom_left; + osmium::Location m_top_right; + + public: + + /** + * Create undefined Box. Use the extend() function + * to add actual bounds. + */ + constexpr Box() : + m_bottom_left(), + m_top_right() { + } + + Box(double minx, double miny, double maxx, double maxy) : + m_bottom_left(minx, miny), + m_top_right(maxx, maxy) { + } + + Box(const osmium::Location& bottom_left, const osmium::Location& top_right) : + m_bottom_left(bottom_left), + m_top_right(top_right) { + } + + Box(const Box&) = default; + Box(Box&&) = default; + Box& operator=(const Box&) = default; + Box& operator=(Box&&) = default; + ~Box() = default; + + /** + * Extend this bounding box by the given location. If the + * location is undefined, the bounding box is unchanged. + */ + Box& extend(const Location& location) noexcept { + if (location) { + if (m_bottom_left) { + if (location.x() < m_bottom_left.x()) { + m_bottom_left.x(location.x()); + } + if (location.x() > m_top_right.x()) { + m_top_right.x(location.x()); + } + if (location.y() < m_bottom_left.y()) { + m_bottom_left.y(location.y()); + } + if (location.y() > m_top_right.y()) { + m_top_right.y(location.y()); + } + } else { + m_bottom_left = location; + m_top_right = location; + } + } + return *this; + } + + /** + * Extend this bounding box by the given box. If the + * box is undefined, the bounding box is unchanged. + */ + Box& extend(const Box& box) noexcept { + extend(box.bottom_left()); + extend(box.top_right()); + return *this; + } + + /** + * Box are defined, ie. contains defined coordinates. + */ + explicit constexpr operator bool() const noexcept { + return static_cast(m_bottom_left); + } + + /** + * Box are valid, ie. defined and inside usual bounds + * (-180<=lon<=180, -90<=lat<=90). + */ + constexpr bool valid() const noexcept { + return bottom_left().valid() && top_right().valid(); + } + + /** + * Bottom-left location. + */ + OSMIUM_CONSTEXPR Location bottom_left() const noexcept { + return m_bottom_left; + } + + /** + * Bottom-left location. + */ + Location& bottom_left() noexcept { + return m_bottom_left; + } + + /** + * Top-right location. + */ + OSMIUM_CONSTEXPR Location top_right() const noexcept { + return m_top_right; + } + + /** + * Top-right location. + */ + Location& top_right() noexcept { + return m_top_right; + } + + /** + * Is the location inside the box? + */ + bool contains(const osmium::Location& location) const { + return location.x() >= bottom_left().x() && location.y() >= bottom_left().y() && + location.x() <= top_right().x() && location.y() <= top_right().y(); + } + + /** + * Calculate size of the box in square degrees. + * + * @throws osmium::invalid_location unless all coordinates are valid + */ + double size() const { + return (m_top_right.lon() - m_bottom_left.lon()) * + (m_top_right.lat() - m_bottom_left.lat()); + } + + }; // class Box + + /** + * Boxes are equal if both locations are equal. + */ + inline OSMIUM_CONSTEXPR bool operator==(const Box& lhs, const Box& rhs) noexcept { + return lhs.bottom_left() == rhs.bottom_left() && lhs.top_right() == rhs.top_right(); + } + + /** + * Output a box to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::Box& box) { + if (box) { + out << '(' + << box.bottom_left().lon() + << ',' + << box.bottom_left().lat() + << ',' + << box.top_right().lon() + << ',' + << box.top_right().lat() + << ')'; + } else { + out << "(undefined)"; + } + return out; + } +} // namespace osmium + +#endif // OSMIUM_OSM_BOX_HPP diff --git a/ThirdParty/osmium/osm/changeset.hpp b/ThirdParty/osmium/osm/changeset.hpp new file mode 100644 index 000000000..e04267cb1 --- /dev/null +++ b/ThirdParty/osmium/osm/changeset.hpp @@ -0,0 +1,340 @@ +#ifndef OSMIUM_OSM_CHANGESET_HPP +#define OSMIUM_OSM_CHANGESET_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace builder { + template class ObjectBuilder; + } + + /** + * An OSM Changeset is of a group of changes made by a single user over a + * short period of time. + */ + class Changeset : public osmium::OSMEntity { + + friend class osmium::builder::ObjectBuilder; + + osmium::Timestamp m_created_at; + osmium::Timestamp m_closed_at; + osmium::Box m_bounds; + changeset_id_type m_id {0}; + num_changes_type m_num_changes {0}; + user_id_type m_uid {0}; + string_size_type m_user_size; + + Changeset() : + OSMEntity(sizeof(Changeset), osmium::item_type::changeset) { + } + + void user_size(string_size_type size) { + m_user_size = size; + } + + unsigned char* subitems_position() { + return data() + osmium::memory::padded_length(sizeof(Changeset) + m_user_size); + } + + const unsigned char* subitems_position() const { + return data() + osmium::memory::padded_length(sizeof(Changeset) + m_user_size); + } + + template + T& subitem_of_type() { + for (iterator it = begin(); it != end(); ++it) { + if (it->type() == T::itemtype) { + return reinterpret_cast(*it); + } + } + + static T subitem; + return subitem; + } + + template + const T& subitem_of_type() const { + for (const_iterator it = cbegin(); it != cend(); ++it) { + if (it->type() == T::itemtype) { + return reinterpret_cast(*it); + } + } + + static const T subitem; + return subitem; + } + + public: + + /// Get ID of this changeset + changeset_id_type id() const noexcept { + return m_id; + } + + /** + * Set ID of this changeset + * + * @return Reference to changeset to make calls chainable. + */ + Changeset& id(changeset_id_type id) noexcept { + m_id = id; + return *this; + } + + /** + * Set ID of this changeset. + * + * @return Reference to object to make calls chainable. + */ + Changeset& id(const char* id) { + return this->id(osmium::string_to_changeset_id(id)); + } + + /// Get user id. + user_id_type uid() const noexcept { + return m_uid; + } + + /** + * Set user id. + * + * @return Reference to changeset to make calls chainable. + */ + Changeset& uid(user_id_type uid) noexcept { + m_uid = uid; + return *this; + } + + /** + * Set user id. + * Sets uid to 0 (anonymous) if the given uid is smaller than 0. + * + * @return Reference to changeset to make calls chainable. + */ + Changeset& uid_from_signed(signed_user_id_type uid) noexcept { + m_uid = uid < 0 ? 0 : static_cast(uid); + return *this; + } + + /** + * Set user id. + * + * @return Reference to changeset to make calls chainable. + */ + Changeset& uid(const char* uid) { + return this->uid_from_signed(string_to_user_id(uid)); + } + + /// Is this user anonymous? + bool user_is_anonymous() const noexcept { + return m_uid == 0; + } + + /// Get timestamp when this changeset was created. + osmium::Timestamp created_at() const noexcept { + return m_created_at; + } + + /** + * Get timestamp when this changeset was closed. + * + * This will return the empty Timestamp when the + * changeset is not yet closed. + */ + osmium::Timestamp closed_at() const noexcept { + return m_closed_at; + } + + bool open() const noexcept { + return m_closed_at == osmium::Timestamp(); + } + + bool closed() const noexcept { + return !open(); + } + + /** + * Set the timestamp when this changeset was created. + * + * @param timestamp Timestamp + * @return Reference to changeset to make calls chainable. + */ + Changeset& created_at(const osmium::Timestamp timestamp) { + m_created_at = timestamp; + return *this; + } + + /** + * Set the timestamp when this changeset was closed. + * + * @param timestamp Timestamp + * @return Reference to changeset to make calls chainable. + */ + Changeset& closed_at(const osmium::Timestamp timestamp) { + m_closed_at = timestamp; + return *this; + } + + num_changes_type num_changes() const noexcept { + return m_num_changes; + } + + Changeset& num_changes(num_changes_type num_changes) noexcept { + m_num_changes = num_changes; + return *this; + } + + Changeset& num_changes(const char* num_changes) noexcept { + return this->num_changes(osmium::string_to_num_changes(num_changes)); + } + + osmium::Box& bounds() noexcept { + return m_bounds; + } + + const osmium::Box& bounds() const noexcept { + return m_bounds; + } + + /// Get user name. + const char* user() const { + return reinterpret_cast(data() + sizeof(Changeset)); + } + + /// Get the list of tags. + TagList& tags() { + return subitem_of_type(); + } + + /// Get the list of tags. + const TagList& tags() const { + return subitem_of_type(); + } + + /** + * Set named attribute. + * + * @param attr Name of the attribute (must be one of "id", "version", "changeset", "timestamp", "uid", "visible") + * @param value Value of the attribute + */ + void set_attribute(const char* attr, const char* value) { + if (!strcmp(attr, "id")) { + id(value); + } else if (!strcmp(attr, "num_changes")) { + num_changes(value); + } else if (!strcmp(attr, "created_at")) { + created_at(osmium::Timestamp(value)); + } else if (!strcmp(attr, "closed_at")) { + closed_at(osmium::Timestamp(value)); + } else if (!strcmp(attr, "uid")) { + uid(value); + } + } + + typedef osmium::memory::CollectionIterator iterator; + typedef osmium::memory::CollectionIterator const_iterator; + + iterator begin() { + return iterator(subitems_position()); + } + + iterator end() { + return iterator(data() + padded_size()); + } + + const_iterator cbegin() const { + return const_iterator(subitems_position()); + } + + const_iterator cend() const { + return const_iterator(data() + padded_size()); + } + + const_iterator begin() const { + return cbegin(); + } + + const_iterator end() const { + return cend(); + } + + }; // class Changeset + + static_assert(sizeof(Changeset) % osmium::memory::align_bytes == 0, "Class osmium::Changeset has wrong size to be aligned properly!"); + + /** + * Changesets are equal if their IDs are equal. + */ + inline bool operator==(const Changeset& lhs, const Changeset& rhs) { + return lhs.id() == rhs.id(); + } + + inline bool operator!=(const Changeset& lhs, const Changeset& rhs) { + return ! (lhs == rhs); + } + + /** + * Changesets can be ordered by id. + */ + inline bool operator<(const Changeset& lhs, const Changeset& rhs) { + return lhs.id() < rhs.id(); + } + + inline bool operator>(const Changeset& lhs, const Changeset& rhs) { + return rhs < lhs; + } + + inline bool operator<=(const Changeset& lhs, const Changeset& rhs) { + return ! (rhs < lhs); + } + + inline bool operator>=(const Changeset& lhs, const Changeset& rhs) { + return ! (lhs < rhs); + } + +} // namespace osmium + +#endif // OSMIUM_OSM_CHANGESET_HPP diff --git a/ThirdParty/osmium/osm/diff_object.hpp b/ThirdParty/osmium/osm/diff_object.hpp new file mode 100644 index 000000000..d3d9c2123 --- /dev/null +++ b/ThirdParty/osmium/osm/diff_object.hpp @@ -0,0 +1,156 @@ +#ifndef OSMIUM_OSM_DIFF_OBJECT_HPP +#define OSMIUM_OSM_DIFF_OBJECT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +namespace osmium { + + class Node; + class Way; + class Relation; + + class DiffObject { + + protected: + + osmium::OSMObject* m_prev; + osmium::OSMObject* m_curr; + osmium::OSMObject* m_next; + + public: + + DiffObject() : + m_prev(nullptr), + m_curr(nullptr), + m_next(nullptr) { + } + + explicit DiffObject(osmium::OSMObject& prev, osmium::OSMObject& curr, osmium::OSMObject& next) : + m_prev(&prev), + m_curr(&curr), + m_next(&next) { + } + + DiffObject(const DiffObject& other) = default; + DiffObject& operator=(const DiffObject& other) = default; + + DiffObject(DiffObject&& other) = default; + DiffObject& operator=(DiffObject&& other) = default; + + const osmium::OSMObject& prev() const { + return *m_prev; + } + + const osmium::OSMObject& curr() const { + return *m_curr; + } + + const osmium::OSMObject& next() const { + return *m_next; + } + + bool first() const { + return m_prev == m_curr; + } + + bool last() const { + return m_curr == m_next; + } + + osmium::item_type type() const { + return m_curr->type(); + } + + osmium::object_id_type id() const { + return m_curr->id(); + } + + osmium::object_version_type version() const { + return m_curr->version(); + } + + osmium::changeset_id_type changeset() const { + return m_curr->changeset(); + } + + const osmium::Timestamp start_time() const { + return m_curr->timestamp(); + } + + const osmium::Timestamp end_time() const { + return last() ? osmium::Timestamp() : m_next->timestamp(); + } + + }; // class DiffObject + + template + class DiffObjectDerived : public DiffObject { + + public: + + DiffObjectDerived(T& prev, T& curr, T& next) : + DiffObject(prev, curr, next) { + } + + DiffObjectDerived(const DiffObjectDerived& other) = default; + DiffObjectDerived& operator=(const DiffObjectDerived& other) = default; + + DiffObjectDerived(DiffObjectDerived&& other) = default; + DiffObjectDerived& operator=(DiffObjectDerived&& other) = default; + + const T& prev() const { + return *static_cast(m_prev); + } + + const T& curr() const { + return *static_cast(m_curr); + } + + const T& next() const { + return *static_cast(m_next); + } + + }; // class DiffObjectDerived + + typedef DiffObjectDerived DiffNode; + typedef DiffObjectDerived DiffWay; + typedef DiffObjectDerived DiffRelation; + +} // namespace osmium + +#endif // OSMIUM_OSM_DIFF_OBJECT_HPP diff --git a/ThirdParty/osmium/osm/entity.hpp b/ThirdParty/osmium/osm/entity.hpp new file mode 100644 index 000000000..9d068f587 --- /dev/null +++ b/ThirdParty/osmium/osm/entity.hpp @@ -0,0 +1,55 @@ +#ifndef OSMIUM_OSM_ENTITY_HPP +#define OSMIUM_OSM_ENTITY_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +namespace osmium { + + /** + * OSMEntity is the parent class for the OSMObject class and the Changeset class. + */ + class OSMEntity : public osmium::memory::Item { + + public: + + explicit OSMEntity(osmium::memory::item_size_type size, osmium::item_type type) : + Item(size, type) { + } + + }; // class OSMEntity + +} // namespace osmium + +#endif // OSMIUM_OSM_ENTITY_HPP diff --git a/ThirdParty/osmium/osm/entity_bits.hpp b/ThirdParty/osmium/osm/entity_bits.hpp new file mode 100644 index 000000000..d6e4a8b75 --- /dev/null +++ b/ThirdParty/osmium/osm/entity_bits.hpp @@ -0,0 +1,93 @@ +#ifndef OSMIUM_OSM_ENTITY_BITS_HPP +#define OSMIUM_OSM_ENTITY_BITS_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +namespace osmium { + + /** + * @brief Bitfield for OSM entity types. + */ + namespace osm_entity_bits { + + /** + * Describes zero or more OSM entities. + * + * Usage: + * + * @code{.cpp} + * osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::node | osmium::osm_entity_bits::way; + * + * entities |= osmium::osm_entity_bits::relation; + * + * assert(entities & osmium::osm_entity_bits::object); + * + * assert(! (entities & osmium::osm_entity_bits::changeset)); + * @endcode + */ + enum type : unsigned char { + + nothing = 0x00, + node = 0x01, + way = 0x02, + relation = 0x04, + area = 0x08, + object = 0x0f, ///< node, way, relation, or area object + changeset = 0x10, + all = 0x1f ///< object or changeset + + }; // enum type + + inline type operator|(const type lhs, const type rhs) { + return static_cast(static_cast(lhs) | static_cast (rhs)); + } + + inline type& operator|=(type& lhs, const type rhs) { + lhs = lhs | rhs; + return lhs; + } + + inline type operator&(const type lhs, const type rhs) { + return static_cast(static_cast(lhs) & static_cast (rhs)); + } + + inline type operator&=(type& lhs, const type rhs) { + lhs = lhs & rhs; + return lhs; + } + + } // namespace osm_entity_bits + +} // namespace osmium + +#endif // OSMIUM_OSM_ENTITY_BITS_HPP diff --git a/ThirdParty/osmium/osm/item_type.hpp b/ThirdParty/osmium/osm/item_type.hpp new file mode 100644 index 000000000..90075d331 --- /dev/null +++ b/ThirdParty/osmium/osm/item_type.hpp @@ -0,0 +1,163 @@ +#ifndef OSMIUM_OSM_ITEM_TYPE_HPP +#define OSMIUM_OSM_ITEM_TYPE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include // IWYU pragma: keep +#include +#include + +namespace osmium { + + enum class item_type : uint16_t { + + undefined = 0x00, + node = 0x01, + way = 0x02, + relation = 0x03, + area = 0x04, + changeset = 0x05, + tag_list = 0x11, + way_node_list = 0x12, + relation_member_list = 0x13, + relation_member_list_with_full_members = 0x23, + outer_ring = 0x40, + inner_ring = 0x41 + + }; // enum class item_type + + inline item_type char_to_item_type(const char c) { + switch (c) { + case 'X': + return item_type::undefined; + case 'n': + return item_type::node; + case 'w': + return item_type::way; + case 'r': + return item_type::relation; + case 'a': + return item_type::area; + case 'c': + return item_type::changeset; + case 'T': + return item_type::tag_list; + case 'N': + return item_type::way_node_list; + case 'M': + return item_type::relation_member_list; + case 'F': + return item_type::relation_member_list_with_full_members; + case 'O': + return item_type::outer_ring; + case 'I': + return item_type::inner_ring; + default: + return item_type::undefined; + } + } + + inline char item_type_to_char(const item_type type) { + switch (type) { + case item_type::undefined: + return 'X'; + case item_type::node: + return 'n'; + case item_type::way: + return 'w'; + case item_type::relation: + return 'r'; + case item_type::area: + return 'a'; + case item_type::changeset: + return 'c'; + case item_type::tag_list: + return 'T'; + case item_type::way_node_list: + return 'N'; + case item_type::relation_member_list: + return 'M'; + case item_type::relation_member_list_with_full_members: + return 'F'; + case item_type::outer_ring: + return 'O'; + case item_type::inner_ring: + return 'I'; + } + } + + inline const char* item_type_to_name(const item_type type) { + switch (type) { + case item_type::undefined: + return "undefined"; + case item_type::node: + return "node"; + case item_type::way: + return "way"; + case item_type::relation: + return "relation"; + case item_type::area: + return "area"; + case item_type::changeset: + return "changeset"; + case item_type::tag_list: + return "tag_list"; + case item_type::way_node_list: + return "way_node_list"; + case item_type::relation_member_list: + return "relation_member_list"; + case item_type::relation_member_list_with_full_members: + return "relation_member_list_with_full_members"; + case item_type::outer_ring: + return "outer_ring"; + case item_type::inner_ring: + return "inner_ring"; + } + } + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const item_type item_type) { + return out << item_type_to_char(item_type); + } + + struct unknown_type : public std::runtime_error { + + unknown_type() : + std::runtime_error("unknown item type") { + } + + }; // struct unknown_type + +} // namespace osmium + +#endif // OSMIUM_OSM_ITEM_TYPE_HPP diff --git a/ThirdParty/osmium/osm/location.hpp b/ThirdParty/osmium/osm/location.hpp new file mode 100644 index 000000000..8884583ad --- /dev/null +++ b/ThirdParty/osmium/osm/location.hpp @@ -0,0 +1,311 @@ +#ifndef OSMIUM_OSM_LOCATION_HPP +#define OSMIUM_OSM_LOCATION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace osmium { + + /** + * Exception signaling an invalid location, ie a location + * outside the -180 to 180 and -90 to 90 degree range. + */ + struct invalid_location : public std::range_error { + + invalid_location(const std::string& what) : + std::range_error(what) { + } + + invalid_location(const char* what) : + std::range_error(what) { + } + + }; // struct invalid_location + + /** + * Locations define a place on earth. + * + * Locations are stored in 32 bit integers for the x and y + * coordinates, respectively. This gives you an accuracy of a few + * centimeters, good enough for OSM use. (The main OSM database + * uses the same scheme.) + * + * An undefined Location can be created by calling the constructor + * without parameters. + * + * Coordinates are never checked on whether they are inside bounds. + * Call valid() to check this. + */ + class Location { + + int32_t m_x; + int32_t m_y; + + public: + + /// this value is used for a coordinate to mark it as undefined + // MSVC doesn't declare std::numeric_limits::max() as + // constexpr, so we hard code this for the time being. + // static constexpr int32_t undefined_coordinate = std::numeric_limits::max(); + static constexpr int32_t undefined_coordinate = 2147483647; + + static constexpr int coordinate_precision = 10000000; + + static int32_t double_to_fix(const double c) noexcept { + return static_cast(std::round(c * coordinate_precision)); + } + + static OSMIUM_CONSTEXPR double fix_to_double(const int32_t c) noexcept { + return static_cast(c) / coordinate_precision; + } + + /** + * Create undefined Location. + */ + explicit constexpr Location() : + m_x(undefined_coordinate), + m_y(undefined_coordinate) { + } + + /** + * Create Location with given x and y coordinates. + * Note that these coordinates are coordinate_precision + * times larger than the real coordinates. + */ + constexpr Location(const int32_t x, const int32_t y) : + m_x(x), + m_y(y) { + } + + /** + * Create Location with given x and y coordinates. + * Note that these coordinates are coordinate_precision + * times larger than the real coordinates. + */ + constexpr Location(const int64_t x, const int64_t y) : + m_x(static_cast(x)), + m_y(static_cast(y)) { + } + + /** + * Create Location with given longitude and latitude. + */ + Location(const double lon, const double lat) : + m_x(double_to_fix(lon)), + m_y(double_to_fix(lat)) { + } + + Location(const Location&) = default; + Location(Location&&) = default; + Location& operator=(const Location&) = default; + Location& operator=(Location&&) = default; + ~Location() = default; + + /** + * Check whether the coordinates of this location + * are defined. + */ + explicit constexpr operator bool() const noexcept { + return m_x != undefined_coordinate && m_y != undefined_coordinate; + } + + /** + * Check whether the coordinates are inside the + * usual bounds (-180<=lon<=180, -90<=lat<=90). + */ + constexpr bool valid() const noexcept { + return m_x >= -180 * coordinate_precision + && m_x <= 180 * coordinate_precision + && m_y >= -90 * coordinate_precision + && m_y <= 90 * coordinate_precision; + } + + constexpr int32_t x() const noexcept { + return m_x; + } + + constexpr int32_t y() const noexcept { + return m_y; + } + + Location& x(const int32_t x) noexcept { + m_x = x; + return *this; + } + + Location& y(const int32_t y) noexcept { + m_y = y; + return *this; + } + + /** + * Get longitude. + * + * @throws invalid_location if the location is invalid + */ + double lon() const { + if (!valid()) { + throw osmium::invalid_location("invalid location"); + } + return fix_to_double(m_x); + } + + /** + * Get longitude without checking the validity. + */ + double lon_without_check() const { + return fix_to_double(m_x); + } + + /** + * Get latitude. + * + * @throws invalid_location if the location is invalid + */ + double lat() const { + if (!valid()) { + throw osmium::invalid_location("invalid location"); + } + return fix_to_double(m_y); + } + + /** + * Get latitude without checking the validity. + */ + double lat_without_check() const { + return fix_to_double(m_y); + } + + Location& lon(double lon) noexcept { + m_x = double_to_fix(lon); + return *this; + } + + Location& lat(double lat) noexcept { + m_y = double_to_fix(lat); + return *this; + } + + static constexpr int coordinate_length = + 1 + /* sign */ + 3 + /* before . */ + 1 + /* . */ + 7 + /* after . */ + 1; /* null byte */ + + template + static T coordinate2string(T iterator, double value) { + char buffer[coordinate_length]; + +#ifndef _MSC_VER + int len = snprintf(buffer, coordinate_length, "%.7f", value); +#else + int len = _snprintf(buffer, coordinate_length, "%.7f", value); +#endif + assert(len > 0 && len < coordinate_length); + while (buffer[len-1] == '0') --len; + if (buffer[len-1] == '.') --len; + + return std::copy_n(buffer, len, iterator); + } + + template + T as_string(T iterator, const char separator) const { + iterator = coordinate2string(iterator, lon()); + *iterator++ = separator; + return coordinate2string(iterator, lat()); + } + + }; // class Location + + /** + * Locations are equal if both coordinates are equal. + */ + inline OSMIUM_CONSTEXPR bool operator==(const Location& lhs, const Location& rhs) noexcept { + return lhs.x() == rhs.x() && lhs.y() == rhs.y(); + } + + inline OSMIUM_CONSTEXPR bool operator!=(const Location& lhs, const Location& rhs) { + return ! (lhs == rhs); + } + + /** + * Compare two locations by comparing first the x and then + * the y coordinate. If either of the locations is + * undefined the result is undefined. + */ + inline OSMIUM_CONSTEXPR bool operator<(const Location& lhs, const Location& rhs) noexcept { + return (lhs.x() == rhs.x() && lhs.y() < rhs.y()) || lhs.x() < rhs.x(); + } + + inline OSMIUM_CONSTEXPR bool operator>(const Location& lhs, const Location& rhs) { + return rhs < lhs; + } + + inline OSMIUM_CONSTEXPR bool operator<=(const Location& lhs, const Location& rhs) { + return ! (rhs < lhs); + } + + inline OSMIUM_CONSTEXPR bool operator>=(const Location& lhs, const Location& rhs) { + return ! (lhs < rhs); + } + + /** + * Output a location to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::Location& location) { + if (location) { + out << '(' << location.lon() << ',' << location.lat() << ')'; + } else { + out << "(undefined,undefined)"; + } + return out; + } + +} // namespace osmium + +#endif // OSMIUM_OSM_LOCATION_HPP diff --git a/ThirdParty/osmium/osm/node.hpp b/ThirdParty/osmium/osm/node.hpp new file mode 100644 index 000000000..e1bc2d0eb --- /dev/null +++ b/ThirdParty/osmium/osm/node.hpp @@ -0,0 +1,80 @@ +#ifndef OSMIUM_OSM_NODE_HPP +#define OSMIUM_OSM_NODE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +namespace osmium { + + namespace builder { + template class ObjectBuilder; + } + + class Node : public OSMObject { + + friend class osmium::builder::ObjectBuilder; + + osmium::Location m_location; + + Node() : + OSMObject(sizeof(Node), osmium::item_type::node) { + } + + public: + + static constexpr osmium::item_type itemtype = osmium::item_type::node; + + const osmium::Location location() const { + return m_location; + } + + osmium::Location& location() { + return m_location; + } + + Node& location(const osmium::Location& location) { + m_location = location; + return *this; + } + + }; // class Node + + static_assert(sizeof(Node) % osmium::memory::align_bytes == 0, "Class osmium::Node has wrong size to be aligned properly!"); + +} // namespace osmium + +#endif // OSMIUM_OSM_NODE_HPP diff --git a/ThirdParty/osmium/osm/node_ref.hpp b/ThirdParty/osmium/osm/node_ref.hpp new file mode 100644 index 000000000..5e10b0ab6 --- /dev/null +++ b/ThirdParty/osmium/osm/node_ref.hpp @@ -0,0 +1,152 @@ +#ifndef OSMIUM_OSM_NODE_REF_HPP +#define OSMIUM_OSM_NODE_REF_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include +#include +#include +#include + +namespace osmium { + + /** + * This reference to a node contains a node ID and a (possibly empty) + * location. + */ + class NodeRef : public osmium::memory::detail::ItemHelper { + + osmium::object_id_type m_ref; + osmium::Location m_location; + + public: + + NodeRef(const osmium::object_id_type ref=0, const osmium::Location& location=Location()) : + m_ref(ref), + m_location(location) { + } + + osmium::object_id_type ref() const { + return m_ref; + } + + osmium::unsigned_object_id_type positive_ref() const { + return static_cast(std::abs(m_ref)); + } + + osmium::Location location() const { + return m_location; + } + + double lon() const { + return m_location.lon(); + } + + double lat() const { + return m_location.lat(); + } + + void location(const osmium::Location& location) { + m_location = location; + } + + }; // class NodeRef + + inline bool operator==(const NodeRef& lhs, const NodeRef& rhs) { + return lhs.ref() == rhs.ref(); + } + + inline bool operator!=(const NodeRef& lhs, const NodeRef& rhs) { + return ! (lhs == rhs); + } + + inline bool operator<(const NodeRef& lhs, const NodeRef& rhs) { + return lhs.ref() < rhs.ref(); + } + + inline bool operator>(const NodeRef& lhs, const NodeRef& rhs) { + return rhs < lhs; + } + + inline bool operator<=(const NodeRef& lhs, const NodeRef& rhs) { + return ! (rhs < lhs); + } + + inline bool operator>=(const NodeRef& lhs, const NodeRef& rhs) { + return ! (lhs < rhs); + } + + /** + * Output a NodeRef to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::NodeRef& nr) { + return out << "<" << nr.ref() << " " << nr.location() << ">"; + } + + /** + * Functor to compare NodeRefs by Location instead of id. + */ + struct location_equal { + + bool operator()(const NodeRef& lhs, const NodeRef& rhs) const { + return lhs.location() == rhs.location(); + } + + typedef NodeRef first_argument_type; + typedef NodeRef second_argument_type; + typedef bool result_type; + + }; // struct location_equal + + /** + * Functor to compare NodeRefs by Location instead of id. + */ + struct location_less { + + bool operator()(const NodeRef& lhs, const NodeRef& rhs) const { + return lhs.location() < rhs.location(); + } + + typedef NodeRef first_argument_type; + typedef NodeRef second_argument_type; + typedef bool result_type; + + }; // struct location_less + +} // namespace osmium + +#endif // OSMIUM_OSM_NODE_REF_HPP diff --git a/ThirdParty/osmium/osm/node_ref_list.hpp b/ThirdParty/osmium/osm/node_ref_list.hpp new file mode 100644 index 000000000..5ece86b06 --- /dev/null +++ b/ThirdParty/osmium/osm/node_ref_list.hpp @@ -0,0 +1,135 @@ +#ifndef OSMIUM_OSM_NODE_REF_LIST_HPP +#define OSMIUM_OSM_NODE_REF_LIST_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include +#include +#include + +namespace osmium { + + /** + * A vector of NodeRef objects. Usually this is not instatiated directly, + * but one of its subclasses are used. + */ + template + class NodeRefList : public osmium::memory::Item { + + public: + + static constexpr osmium::item_type itemtype = TItemType; + + NodeRefList(): + osmium::memory::Item(sizeof(NodeRefList), TItemType) { + } + + bool empty() const { + return sizeof(NodeRefList) == byte_size(); + } + + size_t size() const noexcept { + assert((osmium::memory::Item::byte_size() - sizeof(NodeRefList)) % sizeof(NodeRef) == 0); + return (osmium::memory::Item::byte_size() - sizeof(NodeRefList)) / sizeof(NodeRef); + } + + const NodeRef& operator[](size_t n) const { + const NodeRef* node_ref = &*(this->cbegin()); + return node_ref[n]; + } + + const NodeRef& front() const { + return operator[](0); + } + + const NodeRef& back() const { + return operator[](size()-1); + } + + bool is_closed() const { + return front().ref() == back().ref(); + } + + bool ends_have_same_id() const { + return front().ref() == back().ref(); + } + + bool ends_have_same_location() const { + return front().location() == back().location(); + } + + typedef NodeRef* iterator; + typedef const NodeRef* const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + iterator begin() { + return iterator(data() + sizeof(NodeRefList)); + } + + iterator end() { + return iterator(data() + byte_size()); + } + + const_iterator cbegin() const { + return const_iterator(data() + sizeof(NodeRefList)); + } + + const_iterator cend() const { + return const_iterator(data() + byte_size()); + } + + const_iterator begin() const { + return cbegin(); + } + + const_iterator end() const { + return cend(); + } + + const_reverse_iterator crbegin() const { + return const_reverse_iterator(this->cend()); + } + + const_reverse_iterator crend() const { + return const_reverse_iterator(this->cbegin()); + } + + }; // class NodeRefList + +} // namespace osmium + +#endif // OSMIUM_OSM_NODE_REF_LIST_HPP diff --git a/ThirdParty/osmium/osm/object.hpp b/ThirdParty/osmium/osm/object.hpp new file mode 100644 index 000000000..1ef379892 --- /dev/null +++ b/ThirdParty/osmium/osm/object.hpp @@ -0,0 +1,429 @@ +#ifndef OSMIUM_OSM_OBJECT_HPP +#define OSMIUM_OSM_OBJECT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace osmium { + + /** + * OSMObject (Node, Way, Relation, or Area). + */ + class OSMObject : public osmium::OSMEntity { + + object_id_type m_id; + bool m_deleted : 1; + object_version_type m_version : 31; + osmium::Timestamp m_timestamp; + user_id_type m_uid; + changeset_id_type m_changeset; + + size_t sizeof_object() const { + return sizeof(OSMObject) + (type() == item_type::node ? sizeof(osmium::Location) : 0) + sizeof(string_size_type); + } + + unsigned char* user_position() { + return data() + sizeof_object() - sizeof(string_size_type); + } + + const unsigned char* user_position() const { + return data() + sizeof_object() - sizeof(string_size_type); + } + + string_size_type user_size() const { + return *reinterpret_cast(user_position()); + } + + unsigned char* subitems_position() { + return data() + osmium::memory::padded_length(sizeof_object() + user_size()); + } + + const unsigned char* subitems_position() const { + return data() + osmium::memory::padded_length(sizeof_object() + user_size()); + } + + protected: + + OSMObject(osmium::memory::item_size_type size, osmium::item_type type) : + OSMEntity(size, type), + m_id(0), + m_deleted(false), + m_version(0), + m_timestamp(), + m_uid(0), + m_changeset(0) { + } + + void user_size(string_size_type size) { + *reinterpret_cast(user_position()) = size; + } + + template + T& subitem_of_type() { + for (iterator it = begin(); it != end(); ++it) { + if (it->type() == T::itemtype) { + return reinterpret_cast(*it); + } + } + + static T subitem; + return subitem; + } + + template + const T& subitem_of_type() const { + for (const_iterator it = cbegin(); it != cend(); ++it) { + if (it->type() == T::itemtype) { + return reinterpret_cast(*it); + } + } + + static const T subitem; + return subitem; + } + + public: + + /// Get ID of this object. + object_id_type id() const { + return m_id; + } + + /// Get absolute value of the ID of this object. + unsigned_object_id_type positive_id() const { + return static_cast(std::abs(m_id)); + } + + /** + * Set ID of this object. + * + * @return Reference to object to make calls chainable. + */ + OSMObject& id(object_id_type id) { + m_id = id; + return *this; + } + + /** + * Set ID of this object. + * + * @return Reference to object to make calls chainable. + */ + OSMObject& id(const char* id) { + return this->id(osmium::string_to_object_id(id)); + } + + /// Is this object marked as deleted? + bool deleted() const { + return m_deleted; + } + + /// Is this object marked visible (ie not deleted)? + bool visible() const { + return !deleted(); + } + + /** + * Mark this object as deleted (or not). + * + * @return Reference to object to make calls chainable. + */ + OSMObject& deleted(bool deleted) { + m_deleted = deleted; + return *this; + } + + /** + * Mark this object as visible (ie not deleted) (or not). + * + * @return Reference to object to make calls chainable. + */ + OSMObject& visible(bool visible) { + m_deleted = !visible; + return *this; + } + + /** + * Mark this object as visible (ie not deleted) or deleted. + * + * @param visible Either "true" or "false" + * @return Reference to object to make calls chainable. + */ + OSMObject& visible(const char* visible) { + if (!strcmp("true", visible)) { + this->visible(true); + } else if (!strcmp("false", visible)) { + this->visible(false); + } else { + throw std::invalid_argument("Unknown value for visible attribute (allowed is 'true' or 'false')"); + } + return *this; + } + + /// Get version of this object. + object_version_type version() const { + return m_version; + } + + /** + * Set object version. + * + * @return Reference to object to make calls chainable. + */ + OSMObject& version(object_version_type version) { + m_version = version; + return *this; + } + + /** + * Set object version. + * + * @return Reference to object to make calls chainable. + */ + OSMObject& version(const char* version) { + return this->version(string_to_object_version(version)); + } + + /// Get changeset id of this object. + changeset_id_type changeset() const { + return m_changeset; + } + + /** + * Set changeset id of this object. + * + * @return Reference to object to make calls chainable. + */ + OSMObject& changeset(changeset_id_type changeset) { + m_changeset = changeset; + return *this; + } + + /** + * Set changeset id of this object. + * + * @return Reference to object to make calls chainable. + */ + OSMObject& changeset(const char* changeset) { + return this->changeset(string_to_changeset_id(changeset)); + } + + /// Get user id of this object. + user_id_type uid() const { + return m_uid; + } + + /** + * Set user id of this object. + * + * @return Reference to object to make calls chainable. + */ + OSMObject& uid(user_id_type uid) { + m_uid = uid; + return *this; + } + + /** + * Set user id of this object. + * Sets uid to 0 (anonymous) if the given uid is smaller than 0. + * + * @return Reference to object to make calls chainable. + */ + OSMObject& uid_from_signed(signed_user_id_type uid) { + m_uid = uid < 0 ? 0 : static_cast(uid); + return *this; + } + + /** + * Set user id of this object. + * + * @return Reference to object to make calls chainable. + */ + OSMObject& uid(const char* uid) { + return this->uid_from_signed(string_to_user_id(uid)); + } + + /// Is this user anonymous? + bool user_is_anonymous() const { + return m_uid == 0; + } + + /// Get timestamp when this object last changed. + osmium::Timestamp timestamp() const { + return m_timestamp; + } + + /** + * Set the timestamp when this object last changed. + * + * @param timestamp Timestamp + * @return Reference to object to make calls chainable. + */ + OSMObject& timestamp(const osmium::Timestamp timestamp) { + m_timestamp = timestamp; + return *this; + } + + /// Get user name for this object. + const char* user() const { + return reinterpret_cast(data() + sizeof_object()); + } + + /// Get the list of tags for this object. + TagList& tags() { + return subitem_of_type(); + } + + /// Get the list of tags for this object. + const TagList& tags() const { + return subitem_of_type(); + } + + /** + * Get tag value by key. + * + * Convenience function that will forward to same function on TagList + * object. + */ + const char* get_value_by_key(const char* key, const char* default_value = nullptr) const noexcept { + return tags().get_value_by_key(key, default_value); + } + + /** + * Set named attribute. + * + * @param attr Name of the attribute (must be one of "id", "version", "changeset", "timestamp", "uid", "visible") + * @param value Value of the attribute + */ + void set_attribute(const char* attr, const char* value) { + if (!strcmp(attr, "id")) { + id(value); + } else if (!strcmp(attr, "version")) { + version(value); + } else if (!strcmp(attr, "changeset")) { + changeset(value); + } else if (!strcmp(attr, "timestamp")) { + timestamp(osmium::Timestamp(value)); + } else if (!strcmp(attr, "uid")) { + uid(value); + } else if (!strcmp(attr, "visible")) { + visible(value); + } + } + + typedef osmium::memory::CollectionIterator iterator; + typedef osmium::memory::CollectionIterator const_iterator; + + iterator begin() { + return iterator(subitems_position()); + } + + iterator end() { + return iterator(data() + padded_size()); + } + + const_iterator cbegin() const { + return const_iterator(subitems_position()); + } + + const_iterator cend() const { + return const_iterator(data() + padded_size()); + } + + const_iterator begin() const { + return cbegin(); + } + + const_iterator end() const { + return cend(); + } + + }; // class OSMObject + + static_assert(sizeof(OSMObject) % osmium::memory::align_bytes == 0, "Class osmium::OSMObject has wrong size to be aligned properly!"); + + /** + * OSMObjects are equal if their type, id, and version are equal. + */ + inline bool operator==(const OSMObject& lhs, const OSMObject& rhs) { + return lhs.type() == rhs.type() && + lhs.id() == rhs.id() && + lhs.version() == rhs.version(); + } + + inline bool operator!=(const OSMObject& lhs, const OSMObject& rhs) { + return ! (lhs == rhs); + } + + /** + * OSMObjects can be ordered by type, id and version. + * Note that we use the absolute value of the id for a + * better ordering of objects with negative id. + */ + inline bool operator<(const OSMObject& lhs, const OSMObject& rhs) { + if (lhs.type() != rhs.type()) { + return lhs.type() < rhs.type(); + } + return (lhs.id() == rhs.id() && lhs.version() < rhs.version()) || + lhs.positive_id() < rhs.positive_id(); + } + + inline bool operator>(const OSMObject& lhs, const OSMObject& rhs) { + return rhs < lhs; + } + + inline bool operator<=(const OSMObject& lhs, const OSMObject& rhs) { + return ! (rhs < lhs); + } + + inline bool operator>=(const OSMObject& lhs, const OSMObject& rhs) { + return ! (lhs < rhs); + } + +} // namespace osmium + +#endif // OSMIUM_OSM_OBJECT_HPP diff --git a/ThirdParty/osmium/osm/object_comparisons.hpp b/ThirdParty/osmium/osm/object_comparisons.hpp new file mode 100644 index 000000000..5c2bf6cc6 --- /dev/null +++ b/ThirdParty/osmium/osm/object_comparisons.hpp @@ -0,0 +1,110 @@ +#ifndef OSMIUM_OSM_OBJECT_COMPARISONS_HPP +#define OSMIUM_OSM_OBJECT_COMPARISONS_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +namespace osmium { + + /** + * Function object class for comparing OSM objects for equality by type, id, and version. + */ + struct object_equal_type_id_version { + + bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const { + return lhs == rhs; + } + + bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const { + return *lhs == *rhs; + } + + }; // struct object_equal_type_id_version + + /** + * Function object class for comparing OSM objects for equality by type and id, + * ignoring the version. + */ + struct object_equal_type_id { + + bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const { + return lhs.type() == rhs.type() && + lhs.id() == rhs.id(); + } + + bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const { + return operator()(*lhs, *rhs); + } + + }; // struct object_equal_type_id + + /** + * Function object class for ordering OSM objects by type, id, and version. + */ + struct object_order_type_id_version { + + bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const { + return lhs < rhs; + } + + bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const { + return *lhs < *rhs; + } + + }; // struct object_order_type_id_version + + /** + * Function object class for ordering OSM objects by type, id, and reverse version, + * ie objects are ordered by type and id, but later versions of an object are + * ordered before earlier versions of the same object. + */ + struct object_order_type_id_reverse_version { + + bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const { + if (lhs.type() != rhs.type()) { + return lhs.type() < rhs.type(); + } + return (lhs.id() == rhs.id() && lhs.version() > rhs.version()) || + lhs.positive_id() < rhs.positive_id(); + } + + bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const { + return operator()(*lhs, *rhs); + } + + }; // struct object_order_type_id_reverse_version + +} // namespace osmium + +#endif // OSMIUM_OSM_OBJECT_COMPARISONS_HPP diff --git a/ThirdParty/osmium/osm/relation.hpp b/ThirdParty/osmium/osm/relation.hpp new file mode 100644 index 000000000..7974e7aad --- /dev/null +++ b/ThirdParty/osmium/osm/relation.hpp @@ -0,0 +1,189 @@ +#ifndef OSMIUM_OSM_RELATION_HPP +#define OSMIUM_OSM_RELATION_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +#include // IWYU pragma: keep +#include +#include +#include +#include + +namespace osmium { + + namespace builder { + template class ObjectBuilder; + class RelationMemberListBuilder; + } + + class RelationMember : public osmium::memory::detail::ItemHelper { + + friend class osmium::builder::RelationMemberListBuilder; + + object_id_type m_ref; + item_type m_type; + uint16_t m_flags; + string_size_type m_role_size {0}; + + RelationMember(const RelationMember&) = delete; + RelationMember(RelationMember&&) = delete; + + RelationMember& operator=(const RelationMember&) = delete; + RelationMember& operator=(RelationMember&&) = delete; + + unsigned char* endpos() { + return data() + osmium::memory::padded_length(sizeof(RelationMember) + m_role_size); + } + + const unsigned char* endpos() const { + return data() + osmium::memory::padded_length(sizeof(RelationMember) + m_role_size); + } + + template + friend class osmium::memory::CollectionIterator; + + unsigned char* next() { + if (full_member()) { + return endpos() + reinterpret_cast(endpos())->byte_size(); + } else { + return endpos(); + } + } + + unsigned const char* next() const { + if (full_member()) { + return endpos() + reinterpret_cast(endpos())->byte_size(); + } else { + return endpos(); + } + } + + void set_role_size(string_size_type size) { + m_role_size = size; + } + + public: + + static constexpr item_type collection_type = item_type::relation_member_list; + + RelationMember(const object_id_type ref=0, const item_type type=item_type(), const bool full=false) : + m_ref(ref), + m_type(type), + m_flags(full ? 1 : 0) { + } + + object_id_type ref() const { + return m_ref; + } + + RelationMember& ref(object_id_type ref) { + m_ref = ref; + return *this; + } + + unsigned_object_id_type positive_ref() const { + return static_cast(std::abs(m_ref)); + } + + item_type type() const { + return m_type; + } + + bool full_member() const { + return m_flags == 1; + } + + const char* role() const { + return reinterpret_cast(data() + sizeof(RelationMember)); + } + + OSMObject& get_object() { + return *reinterpret_cast(endpos()); + } + + const OSMObject& get_object() const { + return *reinterpret_cast(endpos()); + } + + }; // class RelationMember + + class RelationMemberList : public osmium::memory::Collection { + + public: + + typedef size_t size_type; + + RelationMemberList() : + osmium::memory::Collection() { + } + + size_type size() const noexcept { + return static_cast(std::distance(begin(), end())); + } + + }; // class RelationMemberList + + static_assert(sizeof(RelationMemberList) % osmium::memory::align_bytes == 0, "Class osmium::RelationMemberList has wrong size to be aligned properly!"); + + class Relation : public OSMObject { + + friend class osmium::builder::ObjectBuilder; + + Relation() : + OSMObject(sizeof(Relation), osmium::item_type::relation) { + } + + public: + + static constexpr osmium::item_type itemtype = osmium::item_type::relation; + + RelationMemberList& members() { + return subitem_of_type(); + } + + const RelationMemberList& members() const { + return subitem_of_type(); + } + + }; // class Relation + + static_assert(sizeof(Relation) % osmium::memory::align_bytes == 0, "Class osmium::Relation has wrong size to be aligned properly!"); + +} // namespace osmium + +#endif // OSMIUM_OSM_RELATION_HPP diff --git a/ThirdParty/osmium/osm/segment.hpp b/ThirdParty/osmium/osm/segment.hpp new file mode 100644 index 000000000..b08679165 --- /dev/null +++ b/ThirdParty/osmium/osm/segment.hpp @@ -0,0 +1,105 @@ +#ifndef OSMIUM_OSM_SEGMENT_HPP +#define OSMIUM_OSM_SEGMENT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include +#include + +namespace osmium { + + /** + * A Segment is the directed connection between two Locations. + */ + class Segment { + + osmium::Location m_first; + osmium::Location m_second; + + public: + + explicit constexpr Segment(const osmium::Location& location1, const osmium::Location& location2) : + m_first(location1), + m_second(location2) { + } + + constexpr Segment(const Segment&) = default; + constexpr Segment(Segment&&) = default; + + Segment& operator=(const Segment&) = default; + Segment& operator=(Segment&&) = default; + + ~Segment() = default; + + /// Return first Location of Segment. + OSMIUM_CONSTEXPR osmium::Location first() const { + return m_first; + } + + /// Return second Location of Segment. + OSMIUM_CONSTEXPR osmium::Location second() const { + return m_second; + } + + protected: + + void swap_locations() { + using std::swap; + swap(m_first, m_second); + } + + }; // class Segment + + /// Segments are equal if both their locations are equal + inline OSMIUM_CONSTEXPR bool operator==(const Segment& lhs, const Segment& rhs) { + return lhs.first() == rhs.first() && lhs.second() == rhs.second(); + } + + inline OSMIUM_CONSTEXPR bool operator!=(const Segment& lhs, const Segment& rhs) { + return ! (lhs == rhs); + } + + /** + * Output Segment to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::Segment& segment) { + return out << segment.first() << "->" << segment.second(); + } + +} // namespace osmium + +#endif // OSMIUM_OSM_SEGMENT_HPP diff --git a/ThirdParty/osmium/osm/tag.hpp b/ThirdParty/osmium/osm/tag.hpp new file mode 100644 index 000000000..df994a134 --- /dev/null +++ b/ThirdParty/osmium/osm/tag.hpp @@ -0,0 +1,140 @@ +#ifndef OSMIUM_OSM_TAG_HPP +#define OSMIUM_OSM_TAG_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace osmium { + + class Tag : public osmium::memory::detail::ItemHelper { + + Tag(const Tag&) = delete; + Tag(Tag&&) = delete; + + Tag& operator=(const Tag&) = delete; + Tag& operator=(Tag&&) = delete; + + template + friend class osmium::memory::CollectionIterator; + + static unsigned char* after_null(unsigned char* ptr) { + return reinterpret_cast(std::strchr(reinterpret_cast(ptr), 0) + 1); + } + + static const unsigned char* after_null(const unsigned char* ptr) { + return reinterpret_cast(std::strchr(reinterpret_cast(ptr), 0) + 1); + } + + unsigned char* next() { + return after_null(after_null(data())); + } + + const unsigned char* next() const { + return after_null(after_null(data())); + } + + public: + + static constexpr item_type collection_type = item_type::tag_list; + + const char* key() const { + return reinterpret_cast(data()); + } + + const char* value() const { + return reinterpret_cast(after_null(data())); + } + + }; // class Tag + + inline bool operator==(const Tag& a, const Tag& b) { + return !std::strcmp(a.key(), b.key()) && !strcmp(a.value(), b.value()); + } + + inline bool operator<(const Tag& a, const Tag& b) { + return (!std::strcmp(a.key(), b.key()) && (std::strcmp(a.value(), b.value()) < 0)) || (std::strcmp(a.key(), b.key()) < 0); + } + + /** + * Output a Tag to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const Tag& tag) { + return out << tag.key() << '=' << tag.value(); + } + + class TagList : public osmium::memory::Collection { + + public: + + typedef size_t size_type; + + TagList() : + osmium::memory::Collection() { + } + + size_type size() const noexcept { + return static_cast(std::distance(begin(), end())); + } + + const char* get_value_by_key(const char* key, const char* default_value = nullptr) const noexcept { + auto result = std::find_if(cbegin(), cend(), [key](const Tag& tag) { + return !strcmp(tag.key(), key); + }); + if (result == cend()) { + return default_value; + } else { + return result->value(); + } + } + + const char* operator[](const char* key) const noexcept { + return get_value_by_key(key); + } + + }; // class TagList + + static_assert(sizeof(TagList) % osmium::memory::align_bytes == 0, "Class osmium::TagList has wrong size to be aligned properly!"); + +} // namespace osmium + +#endif // OSMIUM_OSM_TAG_HPP diff --git a/ThirdParty/osmium/osm/timestamp.hpp b/ThirdParty/osmium/osm/timestamp.hpp new file mode 100644 index 000000000..7e25f83e8 --- /dev/null +++ b/ThirdParty/osmium/osm/timestamp.hpp @@ -0,0 +1,159 @@ +#ifndef OSMIUM_OSM_TIMESTAMP_HPP +#define OSMIUM_OSM_TIMESTAMP_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace osmium { + + /** + * A timestamp. Internal representation is an unsigned 32bit integer + * holding seconds since epoch, so this will overflow in 2038. + */ + class Timestamp { + + // length of ISO timestamp string yyyy-mm-ddThh:mm:ssZ\0 + static constexpr int timestamp_length = 20 + 1; + + /** + * The timestamp format for OSM timestamps in strftime(3) format. + * This is the ISO-Format yyyy-mm-ddThh:mm:ssZ + */ + static const char* timestamp_format() { + static const char f[timestamp_length] = "%Y-%m-%dT%H:%M:%SZ"; + return f; + } + + uint32_t m_timestamp; + + public: + + constexpr Timestamp() : + m_timestamp(0) { + } + + // Not "explicit" so that conversions from time_t work + // like in node.timestamp(123); + constexpr Timestamp(time_t timestamp) : + m_timestamp(static_cast(timestamp)) { + } + + /** + * Construct timestamp from ISO date/time string. + * Throws std::invalid_argument, if the timestamp can not be parsed. + */ + explicit Timestamp(const char* timestamp) { +#ifndef WIN32 + struct tm tm { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + if (strptime(timestamp, timestamp_format(), &tm) == nullptr) { + throw std::invalid_argument("can't parse timestamp"); + } + m_timestamp = static_cast(timegm(&tm)); +#else + struct tm tm; + int n = sscanf(timestamp, "%4d-%2d-%2dT%2d:%2d:%2dZ", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec); + if (n != 6) { + throw std::invalid_argument("can't parse timestamp"); + } + tm.tm_year -= 1900; + tm.tm_mon--; + tm.tm_wday = 0; + tm.tm_yday = 0; + tm.tm_isdst = 0; + m_timestamp = _mkgmtime(&tm); +#endif + } + + constexpr time_t seconds_since_epoch() const { + return static_cast(m_timestamp); + } + + constexpr operator time_t() const { + return static_cast(m_timestamp); + } + + /** + * Return UTC Unix time as string in ISO date/time format. + */ + std::string to_iso() const { + if (m_timestamp == 0) { + return std::string(""); + } + struct tm tm; + time_t sse = seconds_since_epoch(); +#ifndef _MSC_VER + gmtime_r(&sse, &tm); +#else + gmtime_s(&tm, &sse); +#endif + + std::string s(timestamp_length, '\0'); + /* This const_cast is ok, because we know we have enough space + in the string for the format we are using (well at least until + the year will have 5 digits). And by setting the size + afterwards from the result of strftime we make sure thats set + right, too. */ + s.resize(strftime(const_cast(s.c_str()), timestamp_length, timestamp_format(), &tm)); + return s; + } + + }; // class Timestamp + + inline OSMIUM_CONSTEXPR Timestamp start_of_time() { + return Timestamp(1); + } + + inline OSMIUM_CONSTEXPR Timestamp end_of_time() { + return Timestamp(std::numeric_limits::max()); + } + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, Timestamp timestamp) { + out << timestamp.to_iso(); + return out; + } + +} // namespace osmium + +#endif // OSMIUM_OSM_TIMESTAMP_HPP diff --git a/ThirdParty/osmium/osm/types.hpp b/ThirdParty/osmium/osm/types.hpp new file mode 100644 index 000000000..532b5497c --- /dev/null +++ b/ThirdParty/osmium/osm/types.hpp @@ -0,0 +1,83 @@ +#ifndef OSMIUM_OSM_TYPES_HPP +#define OSMIUM_OSM_TYPES_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +namespace osmium { + + /* + * The following typedefs are chosen so that they can represent all needed + * numbers and still be reasonably space efficient. As the OSM database + * needs 64 bit IDs for nodes, this size is used for all object IDs. + */ + typedef int64_t object_id_type; ///< Type for OSM object (node, way, or relation) IDs. + typedef uint64_t unsigned_object_id_type; ///< Type for OSM object (node, way, or relation) IDs where we only allow positive IDs. + typedef uint32_t object_version_type; ///< Type for OSM object version number. + typedef uint32_t changeset_id_type; ///< Type for OSM changeset IDs. + typedef uint32_t user_id_type; ///< Type for OSM user IDs. + typedef int32_t signed_user_id_type; ///< Type for signed OSM user IDs. + typedef uint32_t num_changes_type; ///< Type for changeset num_changes. + + /** + * Size for strings in OSM data such as user names, tag keys, roles, etc. + * In Osmium they can be up to 2^16 bytes long, but OSM usually has lower + * defined limits. + */ + typedef uint16_t string_size_type; + + inline object_id_type string_to_object_id(const char* string) { + return std::atoll(string); + } + + inline object_version_type string_to_object_version(const char* string) { + return static_cast(std::atol(string)); + } + + inline changeset_id_type string_to_changeset_id(const char* string) { + return static_cast(std::atol(string)); + } + + inline signed_user_id_type string_to_user_id(const char* string) { + return static_cast(std::atol(string)); + } + + inline num_changes_type string_to_num_changes(const char* string) { + return static_cast(std::atol(string)); + } + +} // namespace osmium + +#endif // OSMIUM_OSM_TYPES_HPP diff --git a/ThirdParty/osmium/osm/undirected_segment.hpp b/ThirdParty/osmium/osm/undirected_segment.hpp new file mode 100644 index 000000000..8805162ec --- /dev/null +++ b/ThirdParty/osmium/osm/undirected_segment.hpp @@ -0,0 +1,100 @@ +#ifndef OSMIUM_OSM_UNDIRECTED_SEGMENT_HPP +#define OSMIUM_OSM_UNDIRECTED_SEGMENT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +#include +#include + +namespace osmium { + + /** + * Undirected connection between two Locations. The first Location is + * always equal or "smaller" than the second Location, ie to the left + * and down. + */ + class UndirectedSegment : public Segment { + + public: + + explicit UndirectedSegment(const osmium::Location& location1, const osmium::Location& location2) : + Segment(location1, location2) { + if (location2 < location1) { + swap_locations(); + } + } + + UndirectedSegment(const UndirectedSegment&) = default; + UndirectedSegment(UndirectedSegment&&) = default; + + UndirectedSegment& operator=(const UndirectedSegment&) = default; + UndirectedSegment& operator=(UndirectedSegment&&) = default; + + ~UndirectedSegment() = default; + + }; // class UndirectedSegment + + /** + * UndirectedSegments are "smaller" if they are to the left and down of another + * segment. The first() location is checked first() and only if they have the + * same first() location the second() location is taken into account. + */ + inline bool operator<(const UndirectedSegment& lhs, const UndirectedSegment& rhs) { + return (lhs.first() == rhs.first() && lhs.second() < rhs.second()) || lhs.first() < rhs.first(); + } + + inline bool operator>(const UndirectedSegment& lhs, const UndirectedSegment& rhs) { + return rhs < lhs; + } + + inline bool operator<=(const UndirectedSegment& lhs, const UndirectedSegment& rhs) { + return ! (rhs < lhs); + } + + inline bool operator>=(const UndirectedSegment& lhs, const UndirectedSegment& rhs) { + return ! (lhs < rhs); + } + + /** + * Output UndirectedSegment to a stream. + */ + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const osmium::UndirectedSegment& segment) { + return out << segment.first() << "--" << segment.second(); + } + +} // namespace osmium + +#endif // OSMIUM_OSM_UNDIRECTED_SEGMENT_HPP diff --git a/ThirdParty/osmium/osm/way.hpp b/ThirdParty/osmium/osm/way.hpp new file mode 100644 index 000000000..c55698c21 --- /dev/null +++ b/ThirdParty/osmium/osm/way.hpp @@ -0,0 +1,115 @@ +#ifndef OSMIUM_OSM_WAY_HPP +#define OSMIUM_OSM_WAY_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace builder { + template class ObjectBuilder; + } + + /** + * List of node references (id and location) in a way. + */ + class WayNodeList : public NodeRefList { + + public: + + WayNodeList(): + NodeRefList() { + } + + }; // class WayNodeList + + static_assert(sizeof(WayNodeList) % osmium::memory::align_bytes == 0, "Class osmium::WayNodeList has wrong size to be aligned properly!"); + + class Way : public OSMObject { + + friend class osmium::builder::ObjectBuilder; + + Way() : + OSMObject(sizeof(Way), osmium::item_type::way) { + } + + public: + + WayNodeList& nodes() { + return subitem_of_type(); + } + + const WayNodeList& nodes() const { + return subitem_of_type(); + } + + /** + * Update all nodes in a way with the ID of the given NodeRef with the + * location of the given NodeRef. + */ + void update_node_location(const NodeRef& new_node_ref) { + for (auto& node_ref : nodes()) { + if (node_ref.ref() == new_node_ref.ref()) { + node_ref.location(new_node_ref.location()); + } + } + } + + /** + * Do the nodes in this way form a closed ring? + */ + bool is_closed() const { + return nodes().is_closed(); + } + + bool ends_have_same_id() const { + return nodes().ends_have_same_id(); + } + + bool ends_have_same_location() const { + return nodes().ends_have_same_location(); + } + + }; // class Way + + static_assert(sizeof(Way) % osmium::memory::align_bytes == 0, "Class osmium::Way has wrong size to be aligned properly!"); + +} // namespace osmium + +#endif // OSMIUM_OSM_WAY_HPP diff --git a/ThirdParty/osmium/relations/collector.hpp b/ThirdParty/osmium/relations/collector.hpp new file mode 100644 index 000000000..cc7a5964e --- /dev/null +++ b/ThirdParty/osmium/relations/collector.hpp @@ -0,0 +1,535 @@ +#ifndef OSMIUM_RELATIONS_COLLECTOR_HPP +#define OSMIUM_RELATIONS_COLLECTOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include // IWYU pragma: keep +#include +#include +#include +#include + +#include +#include + +namespace osmium { + + class Node; + class Way; + + /** + * @brief Code related to the assembly of OSM relations + */ + namespace relations { + + /** + * The Collector class collects members of a relation. This is a generic + * base class that can be used to assemble all kinds of relations. It has numerous + * hooks you can implement in derived classes to customize its behaviour. + * + * The collector provides two handlers (HandlerPass1 and HandlerPass2) for a first + * and second pass through an input file, respectively. In the first pass all + * relations we are interested in are stored in RelationMeta objects in the + * m_relations vector. All members we are interested in are stored in MemberMeta + * objects in the m_member_meta vectors. + * The MemberMeta objects also store the information where the relations containing + * those members are to be found. + * + * Later the m_member_meta vectors are sorted according to the + * member ids so that a binary search (with std::equal_range) can be used in the second + * pass to find the parent relations for each node, way, or relation coming along. + * The member objects are stored together with their relation and once a relation + * is complete the complete_relation() method is called which you must overwrite in + * a derived class of Collector. + * + * @tparam TCollector Derived class of this class. + * + * @tparam TNodes Are we interested in member nodes? + * + * @tparam TWays Are we interested in member ways? + * + * @tparam TRelations Are we interested in member relations? + */ + template + class Collector { + + /** + * This is the handler class for the first pass of the Collector. + */ + class HandlerPass1 : public osmium::handler::Handler { + + TCollector& m_collector; + + public: + + HandlerPass1(TCollector& collector) : + m_collector(collector) { + } + + void relation(const osmium::Relation& relation) { + if (m_collector.keep_relation(relation)) { + m_collector.add_relation(relation); + } + } + + }; // class HandlerPass1 + + /** + * This is the handler class for the second pass of the Collector. + */ + class HandlerPass2 : public osmium::handler::Handler { + + TCollector& m_collector; + + /** + * This variable is initialized with the number of different + * kinds of OSM objects we are interested in. If we only need + * way members (for instance for the multipolygon collector) + * it is intialized with 1 for instance. If node and way + * members are needed, it is initialized with 2. + * + * In the after_* methods of this handler, it is decremented + * and once it reaches 0, we know we have all members available + * that we are ever going to get. + */ + int m_want_types; + + /** + * Find this object in the member vectors and add it to all + * relations that need it. + * + * @returns true if the member was added to at least one + * relation and false otherwise + */ + bool find_and_add_object(const osmium::OSMObject& object) { + auto& mmv = m_collector.member_meta(object.type()); + auto range = std::equal_range(mmv.begin(), mmv.end(), MemberMeta(object.id())); + + if (range.first == range.second) { + // nothing found + return false; + } + + { + const size_t member_offset = m_collector.members_buffer().committed(); + m_collector.members_buffer().add_item(object); + m_collector.members_buffer().commit(); + + for (auto it = range.first; it != range.second; ++it) { + it->buffer_offset(member_offset); + } + } + + for (auto it = range.first; it != range.second; ++it) { + MemberMeta& member_meta = *it; + assert(member_meta.member_id() == object.id()); + assert(member_meta.relation_pos() < m_collector.m_relations.size()); + RelationMeta& relation_meta = m_collector.m_relations[member_meta.relation_pos()]; +// std::cerr << " => " << member_meta.member_pos() << " < " << m_collector.get_relation(relation_meta).members().size() << " (id=" << m_collector.get_relation(relation_meta).id() << ")\n"; + assert(member_meta.member_pos() < m_collector.get_relation(relation_meta).members().size()); +// std::cerr << " add way " << member_meta.member_id() << " to rel " << m_collector.get_relation(relation_meta).id() << " at pos " << member_meta.member_pos() << "\n"; + relation_meta.got_one_member(); + if (relation_meta.has_all_members()) { + const size_t relation_offset = member_meta.relation_pos(); + m_collector.complete_relation(relation_meta); + m_collector.m_relations[relation_offset] = RelationMeta(); + m_collector.possibly_purge_removed_members(); + } + } + + return true; + } + + public: + + HandlerPass2(TCollector& collector) : + m_collector(collector), + m_want_types((TNodes?1:0) + (TWays?1:0) + (TRelations?1:0)) { + } + + void node(const osmium::Node& node) { + if (TNodes) { + if (! find_and_add_object(node)) { + m_collector.node_not_in_any_relation(node); + } + } + } + + void way(const osmium::Way& way) { + if (TWays) { + if (! find_and_add_object(way)) { + m_collector.way_not_in_any_relation(way); + } + } + } + + void relation(const osmium::Relation& relation) { + if (TRelations) { + if (! find_and_add_object(relation)) { + m_collector.relation_not_in_any_relation(relation); + } + } + } + + void flush() { + m_collector.flush(); + } + + }; // class HandlerPass2 + + HandlerPass2 m_handler_pass2; + + // All relations we are interested in will be kept in this buffer + osmium::memory::Buffer m_relations_buffer; + + // All members we are interested in will be kept in this buffer + osmium::memory::Buffer m_members_buffer; + + /// Vector with all relations we are interested in + std::vector m_relations; + + /** + * One vector each for nodes, ways, and relations containing all + * mappings from member ids to their relations. + */ + std::vector m_member_meta[3]; + + int m_count_complete = 0; + + typedef std::function callback_func_type; + callback_func_type m_callback; + + static constexpr size_t initial_buffer_size = 1024 * 1024; + + public: + + /** + * Create an Collector. + */ + Collector() : + m_handler_pass2(*static_cast(this)), + m_relations_buffer(initial_buffer_size, osmium::memory::Buffer::auto_grow::yes), + m_members_buffer(initial_buffer_size, osmium::memory::Buffer::auto_grow::yes), + m_relations(), + m_member_meta() { + } + + protected: + + std::vector& member_meta(const item_type type) { + return m_member_meta[static_cast(type) - 1]; + } + + callback_func_type callback() { + return m_callback; + } + + const std::vector& relations() const { + return m_relations; + } + + /** + * This method is called from the first pass handler for every + * relation in the input, to check whether it should be kept. + * + * Overwrite this method in a child class to only add relations + * you are interested in, for instance depending on the type tag. + * Storing relations takes a lot of memory, so it makes sense to + * filter this as much as possible. + */ + bool keep_relation(const osmium::Relation& /*relation*/) const { + return true; + } + + /** + * This method is called for every member of every relation that + * should be kept. It should decide if the member is interesting or + * not and return true or false to signal that. Only interesting + * members are later added to the relation. + * + * Overwrite this method in a child class. In the MultiPolygonCollector + * this is for instance used to only keep members of type way and + * ignore all others. + */ + bool keep_member(const osmium::relations::RelationMeta& /*relation_meta*/, const osmium::RelationMember& /*member*/) const { + return true; + } + + /** + * This method is called for all nodes that are not a member of + * any relation. + * + * Overwrite this method in a child class if you are interested + * in this. + */ + void node_not_in_any_relation(const osmium::Node& /*node*/) { + } + + /** + * This method is called for all ways that are not a member of + * any relation. + * + * Overwrite this method in a child class if you are interested + * in this. + */ + void way_not_in_any_relation(const osmium::Way& /*way*/) { + } + + /** + * This method is called for all relations that are not a member of + * any relation. + * + * Overwrite this method in a child class if you are interested + * in this. + */ + void relation_not_in_any_relation(const osmium::Relation& /*relation*/) { + } + + /** + * This method is called from the 2nd pass handler when all objects + * of types we are interested in have been seen. + * + * Overwrite this method in a child class if you are interested + * in this. + * + * Note that even after this call members might be missing if they + * were not in the input file! The derived class has to handle this + * case. + */ + void flush() { + } + + /** + * This removes all relations that have already been assembled + * from the m_relations vector. + */ + void clean_assembled_relations() { + m_relations.erase( + std::remove_if(m_relations.begin(), m_relations.end(), has_all_members()), + m_relations.end() + ); + } + + const osmium::Relation& get_relation(size_t offset) const { + return m_relations_buffer.get(offset); + } + + /** + * Get the relation from a relation_meta. + */ + const osmium::Relation& get_relation(const RelationMeta& relation_meta) const { + return get_relation(relation_meta.relation_offset()); + } + + osmium::OSMObject& get_member(size_t offset) const { + return m_members_buffer.get(offset); + } + + /** + * Tell the Collector that you are interested in this relation + * and want it kept until all members have been assembled and + * it is handed back to you. + * + * The relation is copied and stored in a buffer inside the + * collector. + */ + void add_relation(const osmium::Relation& relation) { + const size_t offset = m_relations_buffer.committed(); + m_relations_buffer.add_item(relation); + + RelationMeta relation_meta(offset); + + int n=0; + for (auto& member : m_relations_buffer.get(offset).members()) { + if (static_cast(this)->keep_member(relation_meta, member)) { + member_meta(member.type()).emplace_back(member.ref(), m_relations.size(), n); + relation_meta.increment_need_members(); + } else { + member.ref(0); // set member id to zero to indicate we are not interested + } + ++n; + } + + assert(offset == m_relations_buffer.committed()); + if (relation_meta.has_all_members()) { + m_relations_buffer.rollback(); + } else { + m_relations_buffer.commit(); + m_relations.push_back(std::move(relation_meta)); +// std::cerr << "added relation id=" << relation.id() << "\n"; + } + } + + /** + * Sort the vectors with the member infos so that we can do binary + * search on them. + */ + void sort_member_meta() { +/* std::cerr << "relations: " << m_relations.size() << "\n"; + std::cerr << "node members: " << m_member_meta[0].size() << "\n"; + std::cerr << "way members: " << m_member_meta[1].size() << "\n"; + std::cerr << "relation members: " << m_member_meta[2].size() << "\n";*/ + std::sort(m_member_meta[0].begin(), m_member_meta[0].end()); + std::sort(m_member_meta[1].begin(), m_member_meta[1].end()); + std::sort(m_member_meta[2].begin(), m_member_meta[2].end()); + } + + public: + + uint64_t used_memory() const { + const uint64_t nmembers = m_member_meta[0].capacity() + m_member_meta[1].capacity() + m_member_meta[2].capacity(); + const uint64_t members = nmembers * sizeof(MemberMeta); + const uint64_t relations = m_relations.capacity() * sizeof(RelationMeta); + const uint64_t relations_buffer_capacity = m_relations_buffer.capacity(); + const uint64_t members_buffer_capacity = m_members_buffer.capacity(); + + std::cout << " nR = m_relations.capacity() ........... = " << std::setw(12) << m_relations.capacity() << "\n"; + std::cout << " nMN = m_member_meta[NODE].capacity() ... = " << std::setw(12) << m_member_meta[0].capacity() << "\n"; + std::cout << " nMW = m_member_meta[WAY].capacity() .... = " << std::setw(12) << m_member_meta[1].capacity() << "\n"; + std::cout << " nMR = m_member_meta[RELATION].capacity() = " << std::setw(12) << m_member_meta[2].capacity() << "\n"; + std::cout << " nM = m_member_meta[*].capacity() ...... = " << std::setw(12) << nmembers << "\n"; + + std::cout << " sRM = sizeof(RelationMeta) ............. = " << std::setw(12) << sizeof(RelationMeta) << "\n"; + std::cout << " sMM = sizeof(MemberMeta) ............... = " << std::setw(12) << sizeof(MemberMeta) << "\n\n"; + + std::cout << " nR * sRM ............................... = " << std::setw(12) << relations << "\n"; + std::cout << " nM * sMM ............................... = " << std::setw(12) << members << "\n"; + std::cout << " relations_buffer_capacity .............. = " << std::setw(12) << relations_buffer_capacity << "\n"; + std::cout << " members_buffer_capacity ................ = " << std::setw(12) << members_buffer_capacity << "\n"; + + const uint64_t total = relations + members + relations_buffer_capacity + members_buffer_capacity; + + std::cout << " total .................................. = " << std::setw(12) << total << "\n"; + std::cout << " =======================================================\n"; + + return relations_buffer_capacity + members_buffer_capacity + relations + members; + } + + /** + * Return reference to second pass handler. + */ + HandlerPass2& handler(const callback_func_type& callback = nullptr) { + m_callback = callback; + return m_handler_pass2; + } + + osmium::memory::Buffer& members_buffer() { + return m_members_buffer; + } + + size_t get_offset(osmium::item_type type, osmium::object_id_type id) { + const auto& mmv = member_meta(type); + const auto range = std::equal_range(mmv.cbegin(), mmv.cend(), MemberMeta(id)); + assert(range.first != range.second); + return range.first->buffer_offset(); + } + + template + void read_relations(TIter begin, TIter end) { + HandlerPass1 handler(*static_cast(this)); + osmium::apply(begin, end, handler); + sort_member_meta(); + } + + template + void read_relations(TSource& source) { + read_relations(std::begin(source), std::end(source)); + source.close(); + } + + void moving_in_buffer(size_t old_offset, size_t new_offset) { + const osmium::OSMObject& object = m_members_buffer.get(old_offset); + auto& mmv = member_meta(object.type()); + auto range = std::equal_range(mmv.begin(), mmv.end(), osmium::relations::MemberMeta(object.id())); + for (auto it = range.first; it != range.second; ++it) { + assert(it->buffer_offset() == old_offset); + it->buffer_offset(new_offset); + } + } + + /** + * Decide whether to purge removed members and then do it. + * + * Currently the purging is done every thousand calls. + * This could probably be improved upon. + */ + void possibly_purge_removed_members() { + ++m_count_complete; + if (m_count_complete > 10000) { // XXX + const size_t size_before = m_members_buffer.committed(); + m_members_buffer.purge_removed(this); + const size_t size_after = m_members_buffer.committed(); + double percent = size_before - size_after; + percent /= size_before; + percent *= 100; + std::cerr << "PURGE (size before=" << size_before << " after=" << size_after << " purged=" << (size_before - size_after) << " / " << static_cast(percent) << "%)\n"; + m_count_complete = 0; + } + } + + /** + * Get a vector with pointers to all Relations that could not + * be completed, because members were missing in the input + * data. + * + * Note that these pointers point into memory allocated and + * owned by the Collector object. + */ + std::vector get_incomplete_relations() const { + std::vector relations; + for (const auto& relation_meta : m_relations) { + if (!relation_meta.has_all_members()) { + relations.push_back(&get_relation(relation_meta)); + } + } + return relations; + } + + }; // class Collector + + } // namespace relations + +} // namespace osmium + +#endif // OSMIUM_RELATIONS_COLLECTOR_HPP diff --git a/ThirdParty/osmium/relations/detail/member_meta.hpp b/ThirdParty/osmium/relations/detail/member_meta.hpp new file mode 100644 index 000000000..f6105e559 --- /dev/null +++ b/ThirdParty/osmium/relations/detail/member_meta.hpp @@ -0,0 +1,131 @@ +#ifndef OSMIUM_RELATIONS_DETAIL_MEMBER_META_HPP +#define OSMIUM_RELATIONS_DETAIL_MEMBER_META_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include + +namespace osmium { + + namespace relations { + + /** + * Helper class for the Collector class. + * + * Stores an object ID and information where the object should be + * stored. + */ + class MemberMeta { + + /** + * Object ID of this relation member. Can be a node, way, or relation ID. + * It depends on the vector in which this object is stored which kind of + * object is referenced here. + */ + osmium::object_id_type m_member_id; + + /** + * Position of the relation this member is a part of in the + * m_relations vector. + */ + size_t m_relation_pos; + + /** + * Position of this member in the list of members of the + * relation this member is a part of. + */ + size_t m_member_pos; + + /** + * Offset in the buffer where the object is stored. + */ + size_t m_buffer_offset { 0 }; + + public: + + /** + * Create new MemberMeta. The variant with zeros for relation_pos and + * member_pos is used to create dummy MemberMeta that can be compared + * to the MemberMeta in the vectors using the equal_range algorithm. + */ + explicit MemberMeta(osmium::object_id_type member_id, size_t relation_pos=0, size_t member_pos=0) : + m_member_id(member_id), + m_relation_pos(relation_pos), + m_member_pos(member_pos) { + } + + osmium::object_id_type member_id() const { + return m_member_id; + } + + size_t relation_pos() const { + return m_relation_pos; + } + + size_t member_pos() const { + return m_member_pos; + } + + size_t buffer_offset() const { + return m_buffer_offset; + } + + void buffer_offset(size_t offset) { + m_buffer_offset = offset; + } + + }; // class MemberMeta + + /** + * Compares two MemberMeta objects by only looking at the member id. + * Used to sort a vector of MemberMeta objects and to later find + * them using binary search. + */ + inline bool operator<(const MemberMeta& a, const MemberMeta& b) { + return a.member_id() < b.member_id(); + } + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const MemberMeta& mm) { + out << "MemberMeta(member_id=" << mm.member_id() << " relation_pos=" << mm.relation_pos() << " member_pos=" << mm.member_pos() << " buffer_offset=" << mm.buffer_offset() << ")"; + return out; + } + + } // namespace relations + +} // namespace osmium + +#endif // OSMIUM_RELATIONS_DETAIL_MEMBER_META_HPP diff --git a/ThirdParty/osmium/relations/detail/relation_meta.hpp b/ThirdParty/osmium/relations/detail/relation_meta.hpp new file mode 100644 index 000000000..a9b184ea6 --- /dev/null +++ b/ThirdParty/osmium/relations/detail/relation_meta.hpp @@ -0,0 +1,136 @@ +#ifndef OSMIUM_RELATIONS_DETAIL_RELATION_META_HPP +#define OSMIUM_RELATIONS_DETAIL_RELATION_META_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +namespace osmium { + + namespace relations { + + /** + * Helper class for the Collector class. + * + * Stores information needed to collect all members of a relation. This + * includes the offset of the relation in a buffer plus the information + * needed to add members to this relation. + */ + class RelationMeta { + + /// The relation we are assembling. + size_t m_relation_offset; + + /** + * The number of members still needed before the relation is complete. + * This will be set to the number of members we are interested in and + * then count down for every member we find. When it is 0, the relation + * is complete. + */ + int m_need_members = 0; + + public: + + /** + * Initialize an empty RelationMeta. This is needed to zero out relations + * that have been completed. + */ + RelationMeta() : + m_relation_offset(0) { + } + + explicit RelationMeta(size_t relation_offset) : + m_relation_offset(relation_offset) { + } + + /** + * Get offset of relation in buffer. + */ + size_t relation_offset() const { + return m_relation_offset; + } + + /** + * Increment the m_need_members counter. + */ + void increment_need_members() { + ++m_need_members; + } + + /** + * This decrements the "members needed" counter. + */ + void got_one_member() { + assert(m_need_members > 0); + --m_need_members; + } + + /** + * Returns true if all members for this relation are available. + */ + bool has_all_members() const { + return m_need_members == 0; + } + + }; // class RelationMeta + + template + inline std::basic_ostream& operator<<(std::basic_ostream& out, const RelationMeta& rm) { + out << "RelationMeta(relation_offset=" << rm.relation_offset() << " has_all_members=" << rm.has_all_members() << ")"; + return out; + } + + /** + * Function object to check if a relation is complete. + */ + struct has_all_members { + + typedef RelationMeta& argument_type; + typedef bool result_type; + + /** + * @return true if this relation is complete, false otherwise. + */ + bool operator()(RelationMeta& relation_info) const { + return relation_info.has_all_members(); + } + + }; // struct has_all_members + + } // namespace relations + +} // namespace osmium + +#endif // OSMIUM_RELATIONS_DETAIL_RELATION_META_HPP diff --git a/ThirdParty/osmium/tags/filter.hpp b/ThirdParty/osmium/tags/filter.hpp new file mode 100644 index 000000000..a55dcf718 --- /dev/null +++ b/ThirdParty/osmium/tags/filter.hpp @@ -0,0 +1,148 @@ +#ifndef OSMIUM_TAGS_FILTER_HPP +#define OSMIUM_TAGS_FILTER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +#include + +#include +#include + +namespace osmium { + + namespace tags { + + template + struct match_key { + bool operator()(const TKey& rule_key, const char* tag_key) { + return rule_key == tag_key; + } + }; + + struct match_key_prefix { + bool operator()(const std::string& rule_key, const char* tag_key) { + return rule_key.compare(0, std::string::npos, tag_key, 0, rule_key.size()) == 0; + } + }; + + template + struct match_value { + bool operator()(const TValue& rule_value, const char* tag_value) { + return rule_value == tag_value; + } + }; + + template <> + struct match_value { + bool operator()(const bool, const char*) { + return true; + } + }; + + template , class TValueComp=match_value> + class Filter { + + typedef TKey key_type; + typedef typename std::conditional::value, bool, TValue>::type value_type; + + struct Rule { + key_type key; + value_type value; + bool ignore_value; + bool result; + + explicit Rule(bool r, bool ignore, const key_type& k, const value_type& v) : + key(k), + value(v), + ignore_value(ignore), + result(r) { + } + + explicit Rule(bool r, bool ignore, const key_type& k) : + key(k), + value(), + ignore_value(ignore), + result(r) { + } + + }; + + std::vector m_rules; + bool m_default_result; + + public: + + typedef Filter filter_type; + typedef const osmium::Tag& argument_type; + typedef bool result_type; + typedef boost::filter_iterator iterator; + + explicit Filter(bool default_result = false) : + m_default_result(default_result) { + } + + template ::value, int>::type = 0> + Filter& add(bool result, const key_type& key, const value_type& value) { + m_rules.emplace_back(result, false, key, value); + return *this; + } + + Filter& add(bool result, const key_type& key) { + m_rules.emplace_back(result, true, key); + return *this; + } + + bool operator()(const osmium::Tag& tag) const { + for (const Rule& rule : m_rules) { + if (TKeyComp()(rule.key, tag.key()) && (rule.ignore_value || TValueComp()(rule.value, tag.value()))) { + return rule.result; + } + } + return m_default_result; + } + + }; // Filter + + typedef Filter KeyValueFilter; + typedef Filter KeyFilter; + typedef Filter KeyPrefixFilter; + + } // namespace tags + +} // namespace osmium + +#endif // OSMIUM_TAGS_FILTER_HPP diff --git a/ThirdParty/osmium/tags/regex_filter.hpp b/ThirdParty/osmium/tags/regex_filter.hpp new file mode 100644 index 000000000..1f30cba7a --- /dev/null +++ b/ThirdParty/osmium/tags/regex_filter.hpp @@ -0,0 +1,58 @@ +#ifndef OSMIUM_TAGS_REGEX_FILTER_HPP +#define OSMIUM_TAGS_REGEX_FILTER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include + +namespace osmium { + + namespace tags { + + template <> + struct match_value { + bool operator()(const std::regex& rule_value, const char* tag_value) { + return std::regex_match(tag_value, rule_value); + } + }; + + typedef Filter RegexFilter; + + } // namespace tags + +} // namespace osmium + +#endif // OSMIUM_TAGS_REGEX_FILTER_HPP diff --git a/ThirdParty/osmium/tags/taglist.hpp b/ThirdParty/osmium/tags/taglist.hpp new file mode 100644 index 000000000..c8c0865d1 --- /dev/null +++ b/ThirdParty/osmium/tags/taglist.hpp @@ -0,0 +1,67 @@ +#ifndef OSMIUM_TAGS_TAGLIST_HPP +#define OSMIUM_TAGS_TAGLIST_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +#include + +namespace osmium { + + /** + * @brief Code related to working with OSM tags + */ + namespace tags { + + template + inline bool match_any_of(const osmium::TagList& tag_list, TFilter&& filter) { + return std::any_of(tag_list.begin(), tag_list.end(), std::forward(filter)); + } + + template + inline bool match_all_of(const osmium::TagList& tag_list, TFilter&& filter) { + return std::all_of(tag_list.begin(), tag_list.end(), std::forward(filter)); + } + + template + inline bool match_none_of(const osmium::TagList& tag_list, TFilter&& filter) { + return std::none_of(tag_list.begin(), tag_list.end(), std::forward(filter)); + } + + } // namespace tags + +} // namespace osmium + +#endif // OSMIUM_TAGS_TAGLIST_HPP diff --git a/ThirdParty/osmium/thread/checked_task.hpp b/ThirdParty/osmium/thread/checked_task.hpp new file mode 100644 index 000000000..75c664c99 --- /dev/null +++ b/ThirdParty/osmium/thread/checked_task.hpp @@ -0,0 +1,106 @@ +#ifndef OSMIUM_THREAD_CHECKED_TASK_HPP +#define OSMIUM_THREAD_CHECKED_TASK_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +namespace osmium { + + namespace thread { + + template + class CheckedTask { + + std::thread m_thread; + std::future m_future; + + public: + + template + explicit CheckedTask(TArgs&&... args) { + std::packaged_task pack_task(T(std::forward(args)...)); + m_future = pack_task.get_future(); + m_thread = std::thread(std::move(pack_task)); + } + + ~CheckedTask() { + // Make sure task is done. + if (m_thread.joinable()) { + m_thread.join(); + } + } + + CheckedTask(const CheckedTask&) = delete; + CheckedTask& operator=(const CheckedTask&) = delete; + + /** + * Check task for exceptions. + * + * If an exception happened in the task, re-throw it in this + * thread. This will not do anything if there was no exception. + */ + void check_for_exception() { + if (m_future.valid() && m_future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { + m_future.get(); + } + } + + /** + * Close the task. This will raise in this thread any exception the + * task generated in the other thread. + */ + void close() { + // If an exception happened in the task, re-throw + // it in this thread. This will block if the task + // isn't finished. + if (m_future.valid()) { + m_future.get(); + } + + // Make sure task is done. + if (m_thread.joinable()) { + m_thread.join(); + } + } + + }; // class CheckedTask + + } // namespace thread + +} // namespace osmium + +#endif // OSMIUM_THREAD_CHECKED_TASK_HPP diff --git a/ThirdParty/osmium/thread/function_wrapper.hpp b/ThirdParty/osmium/thread/function_wrapper.hpp new file mode 100644 index 000000000..ad0d14d49 --- /dev/null +++ b/ThirdParty/osmium/thread/function_wrapper.hpp @@ -0,0 +1,104 @@ +#ifndef OSMIUM_THREAD_FUNCTION_WRAPPER_HPP +#define OSMIUM_THREAD_FUNCTION_WRAPPER_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include + +namespace osmium { + + namespace thread { + + class function_wrapper { + + struct impl_base { + virtual void call() = 0; + virtual ~impl_base() { + } + }; + + std::unique_ptr impl; + + template + struct impl_type : impl_base { + F m_functor; + + impl_type(F&& functor) : + m_functor(std::move(functor)) { + } + + void call() { + m_functor(); + } + }; + + public: + + // Constructor must not be "explicit" for wrapper + // to work seemlessly. + template + function_wrapper(F&& f) : + impl(new impl_type(std::move(f))) { + } + + void operator()() { + impl->call(); + } + + function_wrapper() = default; + + function_wrapper(function_wrapper&& other) : + impl(std::move(other.impl)) { + } + + function_wrapper& operator=(function_wrapper&& other) { + impl = std::move(other.impl); + return *this; + } + + function_wrapper(const function_wrapper&) = delete; + function_wrapper(function_wrapper&) = delete; + function_wrapper& operator=(const function_wrapper&) = delete; + + explicit operator bool() const { + return static_cast(impl); + } + + }; // class function_wrapper + + } // namespace thread + +} // namespace osmium + +#endif // OSMIUM_THREAD_FUNCTION_WRAPPER_HPP diff --git a/ThirdParty/osmium/thread/name.hpp b/ThirdParty/osmium/thread/name.hpp new file mode 100644 index 000000000..20ec5c4b9 --- /dev/null +++ b/ThirdParty/osmium/thread/name.hpp @@ -0,0 +1,61 @@ +#ifndef OSMIUM_THREAD_NAME_HPP +#define OSMIUM_THREAD_NAME_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#ifdef __linux__ +# include +#endif + +namespace osmium { + + namespace thread { + + /** + * Set name of current thread for debugging. This only works on Linux. + */ +#ifdef __linux__ + inline void set_thread_name(const char* name) { + prctl(PR_SET_NAME, name, 0, 0, 0); + } +#else + inline void set_thread_name(const char*) { + // intentionally left blank + } +#endif + + } // namespace thread + +} // namespace osmium + +#endif // OSMIUM_THREAD_NAME_HPP diff --git a/ThirdParty/osmium/thread/pool.hpp b/ThirdParty/osmium/thread/pool.hpp new file mode 100644 index 000000000..2e6d6356f --- /dev/null +++ b/ThirdParty/osmium/thread/pool.hpp @@ -0,0 +1,180 @@ +#ifndef OSMIUM_THREAD_POOL_HPP +#define OSMIUM_THREAD_POOL_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace osmium { + + /** + * @brief Threading-related low-level code + */ + namespace thread { + + /** + * Thread pool. + */ + class Pool { + + // This class makes sure pool threads are joined when the pool is destructed + class thread_joiner { + + std::vector& m_threads; + + public: + + explicit thread_joiner(std::vector& threads) : + m_threads(threads) { + } + + ~thread_joiner() { + for (auto& thread : m_threads) { + if (thread.joinable()) { + thread.join(); + } + } + } + + }; // class thread_joiner + + std::atomic m_done; + osmium::thread::Queue m_work_queue; + std::vector m_threads; + thread_joiner m_joiner; + int m_num_threads; + + void worker_thread() { + osmium::thread::set_thread_name("_osmium_worker"); + while (!m_done) { + function_wrapper task; + m_work_queue.wait_and_pop_with_timeout(task); + if (task) { + task(); + } + } + } + + /** + * Create thread pool with the given number of threads. If + * num_threads is 0, the number of threads is read from + * the environment variable OSMIUM_POOL_THREADS. The default + * value in that case is -2. + * + * If the number of threads is a negative number, it will be + * set to the actual number of cores on the system plus the + * given number, ie it will leave a number of cores unused. + * + * In all cases the minimum number of threads in the pool is 1. + */ + explicit Pool(int num_threads) : + m_done(false), + m_work_queue(), + m_threads(), + m_joiner(m_threads), + m_num_threads(num_threads) { + + if (m_num_threads == 0) { + const char* env_threads = getenv("OSMIUM_POOL_THREADS"); + if (env_threads) { + m_num_threads = std::atoi(env_threads); + } else { + m_num_threads = -2; + } + } + + if (m_num_threads <= 0) { + m_num_threads = std::max(1, static_cast(std::thread::hardware_concurrency()) + m_num_threads); + } + + try { + for (int i=0; i < m_num_threads; ++i) { + m_threads.push_back(std::thread(&Pool::worker_thread, this)); + } + } catch (...) { + m_done = true; + throw; + } + } + + public: + + static constexpr int default_num_threads = 0; + + static Pool& instance() { + static Pool pool(default_num_threads); + return pool; + } + + ~Pool() { + m_done = true; + } + + size_t queue_size() const { + return m_work_queue.size(); + } + + bool queue_empty() const { + return m_work_queue.empty(); + } + + template + std::future::type> submit(TFunction f) { + + typedef typename std::result_of::type result_type; + + std::packaged_task task(std::move(f)); + std::future future_result(task.get_future()); + m_work_queue.push(std::move(task)); + + return future_result; + } + + }; // class Pool + + } // namespace thread + +} // namespace osmium + +#endif // OSMIUM_THREAD_POOL_HPP diff --git a/ThirdParty/osmium/thread/queue.hpp b/ThirdParty/osmium/thread/queue.hpp new file mode 100644 index 000000000..633177e74 --- /dev/null +++ b/ThirdParty/osmium/thread/queue.hpp @@ -0,0 +1,128 @@ +#ifndef OSMIUM_THREAD_QUEUE_HPP +#define OSMIUM_THREAD_QUEUE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include +#include +#include + +namespace osmium { + + namespace thread { + + /** + * A thread-safe queue. + */ + template + class Queue { + + mutable std::mutex m_mutex; + std::queue m_queue; + std::condition_variable m_data_available; + + public: + + Queue() : + m_mutex(), + m_queue(), + m_data_available() { + } + + void push(T value) { + std::lock_guard lock(m_mutex); + m_queue.push(std::move(value)); + m_data_available.notify_one(); + } + + size_t push_and_get_size(T&& value) { + std::lock_guard lock(m_mutex); + m_queue.push(std::forward(value)); + m_data_available.notify_one(); + return m_queue.size(); + } + + void push(T value, int) { + push(value); + } + + void wait_and_pop(T& value) { + std::unique_lock lock(m_mutex); + m_data_available.wait(lock, [this] { + return !m_queue.empty(); + }); + value=std::move(m_queue.front()); + m_queue.pop(); + } + + void wait_and_pop_with_timeout(T& value) { + std::unique_lock lock(m_mutex); + if (!m_data_available.wait_for(lock, std::chrono::seconds(1), [this] { + return !m_queue.empty(); + })) { + return; + } + value=std::move(m_queue.front()); + m_queue.pop(); + } + + bool try_pop(T& value) { + std::lock_guard lock(m_mutex); + if (m_queue.empty()) { + return false; + } + value=std::move(m_queue.front()); + m_queue.pop(); + return true; + } + + bool empty() const { + std::lock_guard lock(m_mutex); + return m_queue.empty(); + } + + size_t size() const { + std::lock_guard lock(m_mutex); + return m_queue.size(); + } + + }; // class Queue + + } // namespace thread + +} // namespace osmium + +#endif // OSMIUM_THREAD_QUEUE_HPP diff --git a/ThirdParty/osmium/thread/sorted_queue.hpp b/ThirdParty/osmium/thread/sorted_queue.hpp new file mode 100644 index 000000000..e33dfe696 --- /dev/null +++ b/ThirdParty/osmium/thread/sorted_queue.hpp @@ -0,0 +1,159 @@ +#ifndef OSMIUM_THREAD_SORTED_QUEUE_HPP +#define OSMIUM_THREAD_SORTED_QUEUE_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +namespace osmium { + + namespace thread { + + /** + * This implements a sorted queue. It is a bit like a priority + * queue. We have n worker threads pushing items into the queue + * and one thread pulling them out again "in order". The order + * is defined by the monotonically increasing "num" parameter + * to the push() method. The wait_and_pop() and try_pop() methods + * will only give out the next numbered item. This way several + * workers can work in their own time on different pieces of + * some incoming data, but it all gets serialized properly again + * after the workers have done their work. + */ + template + class SortedQueue { + + typedef typename std::deque::size_type size_type; + + mutable std::mutex m_mutex; + std::deque m_queue; + std::condition_variable m_data_available; + + size_type m_offset; + + // this method expects that we already have the lock + bool empty_intern() const { + return m_queue.front() == T(); + } + + public: + + SortedQueue() : + m_mutex(), + m_queue(1), + m_data_available(), + m_offset(0) { + } + + /** + * Push an item into the queue. + * + * @param value The item to push into the queue. + * @param num Number to describe ordering for the items. + * It must increase monotonically. + */ + void push(T value, size_type num) { + std::lock_guard lock(m_mutex); + + num -= m_offset; + if (m_queue.size() <= num + 1) { + m_queue.resize(num + 2); + } + m_queue[num] = std::move(value); + + m_data_available.notify_one(); + } + + /** + * Wait until the next item becomes available and make it + * available through value. + */ + void wait_and_pop(T& value) { + std::unique_lock lock(m_mutex); + + m_data_available.wait(lock, [this] { + return !empty_intern(); + }); + value=std::move(m_queue.front()); + m_queue.pop_front(); + ++m_offset; + } + + /** + * Get next item if it is available and return true. Or + * return false otherwise. + */ + bool try_pop(T& value) { + std::lock_guard lock(m_mutex); + + if (empty_intern()) { + return false; + } + value=std::move(m_queue.front()); + m_queue.pop_front(); + ++m_offset; + return true; + } + + /** + * The queue is empty. This means try_pop() would fail if called. + * It does not mean that there is nothing on the queue. Because + * the queue is sorted, it could mean that the next item in the + * queue is not available, but other items are. + */ + bool empty() const { + std::lock_guard lock(m_mutex); + + return empty_intern(); + } + + /** + * Returns the number of items in the queue, regardless of whether + * they can be accessed. If this is =0 it + * implies empty()==true, but not the other way around. + */ + size_t size() const { + std::lock_guard lock(m_mutex); + return m_queue.size(); + } + + }; // class SortedQueue + + } // namespace thread + +} // namespace osmium + +#endif // OSMIUM_THREAD_SORTED_QUEUE_HPP diff --git a/ThirdParty/osmium/util/compatibility.hpp b/ThirdParty/osmium/util/compatibility.hpp new file mode 100644 index 000000000..dfd854cc3 --- /dev/null +++ b/ThirdParty/osmium/util/compatibility.hpp @@ -0,0 +1,47 @@ +#ifndef OSMIUM_CONFIG_CONSTEXPR_HPP +#define OSMIUM_CONFIG_CONSTEXPR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +// Workarounds for MSVC which doesn't support +// * constexpr in all cases yet +// * [[noreturn]] +#ifdef _MSC_VER +# define OSMIUM_CONSTEXPR +# define OSMIUM_NORETURN __declspec(noreturn) +#else +# define OSMIUM_CONSTEXPR constexpr +# define OSMIUM_NORETURN [[noreturn]] +#endif + +#endif // OSMIUM_CONFIG_CONSTEXPR_HPP diff --git a/ThirdParty/osmium/util/options.hpp b/ThirdParty/osmium/util/options.hpp new file mode 100644 index 000000000..fc74980d1 --- /dev/null +++ b/ThirdParty/osmium/util/options.hpp @@ -0,0 +1,155 @@ +#ifndef OSMIUM_UTIL_OPTIONS_HPP +#define OSMIUM_UTIL_OPTIONS_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include +#include + +namespace osmium { + + namespace util { + + /** + * Stores key=value type options. This class can be used stand-alone or + * as a base class. Options are stored and retrieved by key using the + * different set() and get() methods. + * + * You can iterate over all set options. Dereferencing an iterator + * yields a std::pair of the key and value strings. + */ + class Options { + + typedef std::map option_map; + option_map m_options; + + public: + + typedef option_map::iterator iterator; + typedef option_map::const_iterator const_iterator; + typedef option_map::value_type value_type; + + Options() = default; + + explicit Options(const std::initializer_list& values) : + m_options(values) { + } + + Options(const Options&) = default; + Options& operator=(const Options&) = default; + + Options(Options&&) = default; + Options& operator=(Options&&) = default; + + ~Options() = default; + + void set(const std::string& key, const std::string& value) { + m_options[key] = value; + } + + void set(const std::string& key, const char* value) { + m_options[key] = value; + } + + void set(const std::string& key, bool value) { + m_options[key] = value ? "true" : "false"; + } + + void set(std::string data) { + size_t pos = data.find_first_of('='); + if (pos == std::string::npos) { + m_options[data] = "true"; + } else { + std::string value = data.substr(pos+1); + data.erase(pos); + set(data, value); + } + } + + /** + * Get value of "key" option. If not set the default_value (or + * empty string) is returned. + */ + std::string get(const std::string& key, const std::string& default_value="") const noexcept { + auto it = m_options.find(key); + if (it == m_options.end()) { + return default_value; + } + return it->second; + } + + /** + * Is this option set to a true value ("true" or "yes")? + */ + bool is_true(const std::string& key) const noexcept { + std::string value = get(key); + return (value == "true" || value == "yes"); + } + + size_t size() const noexcept { + return m_options.size(); + } + + iterator begin() noexcept { + return m_options.begin(); + } + + iterator end() noexcept { + return m_options.end(); + } + + const_iterator begin() const noexcept { + return m_options.cbegin(); + } + + const_iterator end() const noexcept { + return m_options.cend(); + } + + const_iterator cbegin() const noexcept { + return m_options.cbegin(); + } + + const_iterator cend() const noexcept { + return m_options.cend(); + } + + }; // class Options + + } // namespace util + +} // namespace osmium + +#endif // OSMIUM_UTIL_OPTIONS_HPP diff --git a/ThirdParty/osmium/util/verbose_output.hpp b/ThirdParty/osmium/util/verbose_output.hpp new file mode 100644 index 000000000..9925ceee4 --- /dev/null +++ b/ThirdParty/osmium/util/verbose_output.hpp @@ -0,0 +1,139 @@ +#ifndef OSMIUM_UTIL_VERBOSE_OUTPUT_HPP +#define OSMIUM_UTIL_VERBOSE_OUTPUT_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +#include +#include +#include + +namespace osmium { + + /** + * @brief Helpful utility classes and functions not strictly OSM related + */ + namespace util { + + /** + * Osmium programs often run for a long time because of the amount of + * OSM data processed. This class helps with keeping the user up to + * date by offering an easy way for programs to optionally output + * verbose information about what's going on. + * + * Use an object of this class instead of std::cerr as an output + * stream. Nothing is actually written if the object is not set to + * verbose mode. If it is set to verbose mode, each line is prepended + * with the running time, ie the time since the VerboseOutput object + * was created. + */ + class VerboseOutput { + + /// all time output will be relative to this start time + time_t m_start; + + /// is verbose mode enabled? + bool m_verbose; + + /// a newline was written, start next output with runtime + bool m_newline; + + /** + * If we remember that a newline was written as the last thing + * write out the time elapsed and reset the newline flag. + */ + void start_line() { + if (m_newline) { + time_t elapsed = runtime(); + + char old_fill = std::cerr.fill(); + std::cerr << '[' << std::setw(2) << (elapsed / 60) << ':' << std::setw(2) << std::setfill('0') << (elapsed % 60) << "] "; + std::cerr.fill(old_fill); + + m_newline = false; + } + } + + public: + + explicit VerboseOutput(bool verbose=false) : + m_start(time(NULL)), + m_verbose(verbose), + m_newline(true) { + } + + ~VerboseOutput() = default; + + VerboseOutput(const VerboseOutput&) = default; + VerboseOutput& operator=(const VerboseOutput&) = default; + VerboseOutput(VerboseOutput&&) = default; + VerboseOutput& operator=(VerboseOutput&&) = default; + + time_t runtime() const noexcept { + return time(NULL) - m_start; + } + + /// Get "verbose" setting. + bool verbose() const noexcept { + return m_verbose; + } + + /// Set "verbose" setting. + void verbose(bool verbose) noexcept { + m_verbose = verbose; + } + + template + friend VerboseOutput& operator<<(VerboseOutput& verbose_output, const T& value) { + if (verbose_output.m_verbose) { + verbose_output.start_line(); + std::cerr << value; + + // check if there was a newline a the end and remember that + std::ostringstream output_buffer; + output_buffer << value; + if (!output_buffer.str().empty() && output_buffer.str().back() == '\n') { + verbose_output.m_newline = true; + } + } + return verbose_output; + } + + }; // class VerboseOutput + + } // namespace util + +} // namespace osmium + +#endif // OSMIUM_UTIL_VERBOSE_OUTPUT_HPP diff --git a/ThirdParty/osmium/visitor.hpp b/ThirdParty/osmium/visitor.hpp new file mode 100644 index 000000000..e7d97b0fc --- /dev/null +++ b/ThirdParty/osmium/visitor.hpp @@ -0,0 +1,255 @@ +#ifndef OSMIUM_VISITOR_HPP +#define OSMIUM_VISITOR_HPP + +/* + +This file is part of Osmium (http://osmcode.org/libosmium). + +Copyright 2013,2014 Jochen Topf and others (see README). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +*/ + +#include + +#include // IWYU pragma: keep +#include +#include +#include +#include + +namespace osmium { + + class TagList; + class WayNodeList; + class RelationMemberList; + class OuterRing; + class InnerRing; + + namespace memory { + class Item; + } + + namespace detail { + + template + using ConstIfConst = typename std::conditional::value, typename std::add_const::type, U>::type; + + template + inline void apply_item_recurse(TItem& item, THandler& handler) { + switch (item.type()) { + case osmium::item_type::undefined: + break; + case osmium::item_type::node: + handler.osm_object(static_cast&>(item)); + handler.node(static_cast&>(item)); + break; + case osmium::item_type::way: + handler.osm_object(static_cast&>(item)); + handler.way(static_cast&>(item)); + break; + case osmium::item_type::relation: + handler.osm_object(static_cast&>(item)); + handler.relation(static_cast&>(item)); + break; + case osmium::item_type::area: + handler.osm_object(static_cast&>(item)); + handler.area(static_cast&>(item)); + break; + case osmium::item_type::changeset: + handler.changeset(static_cast&>(item)); + break; + case osmium::item_type::tag_list: + handler.tag_list(static_cast&>(item)); + break; + case osmium::item_type::way_node_list: + handler.way_node_list(static_cast&>(item)); + break; + case osmium::item_type::relation_member_list: + case osmium::item_type::relation_member_list_with_full_members: + handler.relation_member_list(static_cast&>(item)); + break; + case osmium::item_type::outer_ring: + handler.outer_ring(static_cast&>(item)); + break; + case osmium::item_type::inner_ring: + handler.inner_ring(static_cast&>(item)); + break; + } + } + + template + inline void apply_item_recurse(const osmium::OSMEntity& item, THandler& handler) { + switch (item.type()) { + case osmium::item_type::node: + handler.osm_object(static_cast(item)); + handler.node(static_cast(item)); + break; + case osmium::item_type::way: + handler.osm_object(static_cast(item)); + handler.way(static_cast(item)); + break; + case osmium::item_type::relation: + handler.osm_object(static_cast(item)); + handler.relation(static_cast(item)); + break; + case osmium::item_type::area: + handler.osm_object(static_cast(item)); + handler.area(static_cast(item)); + break; + case osmium::item_type::changeset: + handler.changeset(static_cast(item)); + break; + default: + throw osmium::unknown_type(); + } + } + + template + inline void apply_item_recurse(osmium::OSMEntity& item, THandler& handler) { + switch (item.type()) { + case osmium::item_type::node: + handler.osm_object(static_cast(item)); + handler.node(static_cast(item)); + break; + case osmium::item_type::way: + handler.osm_object(static_cast(item)); + handler.way(static_cast(item)); + break; + case osmium::item_type::relation: + handler.osm_object(static_cast(item)); + handler.relation(static_cast(item)); + break; + case osmium::item_type::area: + handler.osm_object(static_cast(item)); + handler.area(static_cast(item)); + break; + case osmium::item_type::changeset: + handler.changeset(static_cast(item)); + break; + default: + throw osmium::unknown_type(); + } + } + + template + inline void apply_item_recurse(const osmium::OSMObject& item, THandler& handler) { + switch (item.type()) { + case osmium::item_type::node: + handler.osm_object(item); + handler.node(static_cast(item)); + break; + case osmium::item_type::way: + handler.osm_object(item); + handler.way(static_cast(item)); + break; + case osmium::item_type::relation: + handler.osm_object(item); + handler.relation(static_cast(item)); + break; + case osmium::item_type::area: + handler.osm_object(item); + handler.area(static_cast(item)); + break; + default: + throw osmium::unknown_type(); + } + } + + template + inline void apply_item_recurse(osmium::OSMObject& item, THandler& handler) { + switch (item.type()) { + case osmium::item_type::node: + handler.osm_object(item); + handler.node(static_cast(item)); + break; + case osmium::item_type::way: + handler.osm_object(item); + handler.way(static_cast(item)); + break; + case osmium::item_type::relation: + handler.osm_object(item); + handler.relation(static_cast(item)); + break; + case osmium::item_type::area: + handler.osm_object(item); + handler.area(static_cast(item)); + break; + default: + throw osmium::unknown_type(); + } + } + + template + inline void apply_item_recurse(TItem& item, THandler& handler, TRest&... more) { + apply_item_recurse(item, handler); + apply_item_recurse(item, more...); + } + + template + inline void flush_recurse(THandler& handler) { + handler.flush(); + } + + template + inline void flush_recurse(THandler& handler, TRest&... more) { + flush_recurse(handler); + flush_recurse(more...); + } + + } // namespace detail + + template + inline void apply_item(const osmium::memory::Item& item, THandlers&... handlers) { + detail::apply_item_recurse(item, handlers...); + } + + template + inline void apply_item(osmium::memory::Item& item, THandlers&... handlers) { + detail::apply_item_recurse(item, handlers...); + } + + template + inline void apply(TIterator it, TIterator end, THandlers&... handlers) { + for (; it != end; ++it) { + detail::apply_item_recurse(*it, handlers...); + } + detail::flush_recurse(handlers...); + } + + template + inline void apply(TContainer& c, THandlers&... handlers) { + apply(std::begin(c), std::end(c), handlers...); + } + + template + inline void apply(const osmium::memory::Buffer& buffer, THandlers&... handlers) { + apply(buffer.cbegin(), buffer.cend(), handlers...); + } + +} // namespace osmium + +#endif // OSMIUM_VISITOR_HPP