bump osmium version
This commit is contained in:
+3
-7
@@ -189,8 +189,8 @@ namespace osmium {
|
||||
OPLOutputBlock(const OPLOutputBlock&) = delete;
|
||||
OPLOutputBlock& operator=(const OPLOutputBlock&) = delete;
|
||||
|
||||
OPLOutputBlock(OPLOutputBlock&& other) = default;
|
||||
OPLOutputBlock& operator=(OPLOutputBlock&& other) = default;
|
||||
OPLOutputBlock(OPLOutputBlock&&) = default;
|
||||
OPLOutputBlock& operator=(OPLOutputBlock&&) = default;
|
||||
|
||||
std::string operator()() {
|
||||
osmium::apply(m_input_buffer.cbegin(), m_input_buffer.cend(), *this);
|
||||
@@ -282,11 +282,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void write_buffer(osmium::memory::Buffer&& buffer) override final {
|
||||
osmium::thread::SharedPtrWrapper<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
|
||||
}
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(OPLOutputBlock{std::move(buffer)}));
|
||||
}
|
||||
|
||||
void close() override final {
|
||||
|
||||
+156
-156
@@ -1,156 +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 <jochen@topf.org> 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 <functional>
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/io/file.hpp>
|
||||
#include <osmium/io/file_format.hpp>
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/thread/queue.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace memory {
|
||||
class Buffer;
|
||||
}
|
||||
|
||||
namespace io {
|
||||
|
||||
namespace detail {
|
||||
|
||||
typedef osmium::thread::Queue<std::future<std::string>> 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<osmium::io::detail::OutputFormat*(const osmium::io::File&, data_queue_type&)> create_output_type;
|
||||
|
||||
private:
|
||||
|
||||
typedef std::map<osmium::io::file_format, create_output_type> 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<osmium::io::detail::OutputFormat> 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<osmium::io::detail::OutputFormat>((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
|
||||
#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 <jochen@topf.org> 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 <functional>
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/io/file.hpp>
|
||||
#include <osmium/io/file_format.hpp>
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/thread/queue.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace memory {
|
||||
class Buffer;
|
||||
}
|
||||
|
||||
namespace io {
|
||||
|
||||
namespace detail {
|
||||
|
||||
typedef osmium::thread::Queue<std::future<std::string>> 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<osmium::io::detail::OutputFormat*(const osmium::io::File&, data_queue_type&)> create_output_type;
|
||||
|
||||
private:
|
||||
|
||||
typedef std::map<osmium::io::file_format, create_output_type> 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<osmium::io::detail::OutputFormat> 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<osmium::io::detail::OutputFormat>((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
|
||||
|
||||
Vendored
+17
@@ -46,6 +46,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include <osmium/io/error.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
|
||||
namespace osmium {
|
||||
@@ -78,6 +79,22 @@ namespace osmium {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when there was a problem with parsing the PBF format of
|
||||
* a file.
|
||||
*/
|
||||
struct pbf_error : public io_error {
|
||||
|
||||
pbf_error(const std::string& what) :
|
||||
io_error(std::string("PBF error: ") + what) {
|
||||
}
|
||||
|
||||
pbf_error(const char* what) :
|
||||
io_error(std::string("PBF error: ") + what) {
|
||||
}
|
||||
|
||||
}; // struct pbf_error
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_DETAIL_PBF_HPP
|
||||
|
||||
+53
-511
@@ -47,14 +47,14 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/io/detail/input_format.hpp>
|
||||
#include <osmium/io/detail/pbf.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/detail/zlib.hpp>
|
||||
#include <osmium/io/detail/pbf_parser.hpp>
|
||||
#include <osmium/io/error.hpp>
|
||||
#include <osmium/io/file.hpp>
|
||||
#include <osmium/io/file_format.hpp>
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm.hpp>
|
||||
#include <osmium/osm/box.hpp>
|
||||
@@ -62,486 +62,22 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/object.hpp>
|
||||
#include <osmium/osm/timestamp.hpp>
|
||||
#include <osmium/thread/name.hpp>
|
||||
#include <osmium/thread/pool.hpp>
|
||||
#include <osmium/thread/queue.hpp>
|
||||
#include <osmium/thread/util.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
#include <osmium/util/config.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* Exception thrown when there was a problem with parsing the PBF format of
|
||||
* a file.
|
||||
*/
|
||||
struct pbf_error : public io_error {
|
||||
|
||||
pbf_error(const std::string& what) :
|
||||
io_error(std::string("PBF error: ") + what) {
|
||||
}
|
||||
|
||||
pbf_error(const char* what) :
|
||||
io_error(std::string("PBF error: ") + what) {
|
||||
}
|
||||
|
||||
}; // struct pbf_error
|
||||
|
||||
namespace io {
|
||||
|
||||
class File;
|
||||
|
||||
namespace detail {
|
||||
|
||||
class PBFPrimitiveBlockParser {
|
||||
|
||||
static constexpr size_t initial_buffer_size = 2 * 1024 * 1024;
|
||||
|
||||
const void* m_data;
|
||||
const int 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 int 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 osmium::pbf_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 osmium::pbf_error("group of unknown type");
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(m_buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <class TBuilder, class TPBFObject>
|
||||
void parse_attributes(TBuilder& builder, const TPBFObject& pbf_object) {
|
||||
auto& object = builder.object();
|
||||
|
||||
object.set_id(pbf_object.id());
|
||||
|
||||
if (pbf_object.has_info()) {
|
||||
object.set_version(static_cast_with_assert<object_version_type>(pbf_object.info().version()))
|
||||
.set_changeset(static_cast_with_assert<changeset_id_type>(pbf_object.info().changeset()))
|
||||
.set_timestamp(pbf_object.info().timestamp() * m_date_factor)
|
||||
.set_uid_from_signed(pbf_object.info().uid());
|
||||
if (pbf_object.info().has_visible()) {
|
||||
object.set_visible(pbf_object.info().visible());
|
||||
}
|
||||
builder.add_user(m_stringtable->s(static_cast_with_assert<int>(pbf_object.info().user_sid())));
|
||||
} else {
|
||||
builder.add_user("", 1);
|
||||
}
|
||||
}
|
||||
|
||||
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().set_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<int>(pbf_node.keys(tag))),
|
||||
m_stringtable->s(static_cast<int>(pbf_node.vals(tag))));
|
||||
}
|
||||
}
|
||||
|
||||
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<int>(pbf_way.keys(tag))),
|
||||
m_stringtable->s(static_cast<int>(pbf_way.vals(tag))));
|
||||
}
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
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<int>(pbf_relation.keys(tag))),
|
||||
m_stringtable->s(static_cast<int>(pbf_relation.vals(tag))));
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
m_stringtable->s(dense.keys_vals(n)));
|
||||
|
||||
++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.set_id(last_dense_id);
|
||||
|
||||
if (dense.has_denseinfo()) {
|
||||
auto v = dense.denseinfo().version(i);
|
||||
assert(v > 0);
|
||||
node.set_version(static_cast<osmium::object_version_type>(v));
|
||||
node.set_changeset(static_cast<osmium::changeset_id_type>(last_dense_changeset));
|
||||
node.set_timestamp(last_dense_timestamp * m_date_factor);
|
||||
node.set_uid_from_signed(static_cast<osmium::signed_user_id_type>(last_dense_uid));
|
||||
node.set_visible(visible);
|
||||
builder.add_user(m_stringtable->s(static_cast<int>(last_dense_user_sid)));
|
||||
} else {
|
||||
builder.add_user("", 1);
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
builder.object().set_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<std::future<osmium::memory::Buffer>> queue_type;
|
||||
|
||||
class InputQueueReader {
|
||||
|
||||
osmium::thread::Queue<std::string>& m_queue;
|
||||
std::string m_buffer;
|
||||
|
||||
public:
|
||||
|
||||
InputQueueReader(osmium::thread::Queue<std::string>& 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;
|
||||
}
|
||||
|
||||
}; // class InputQueueReader
|
||||
|
||||
template <class TDerived>
|
||||
class BlobParser {
|
||||
|
||||
protected:
|
||||
|
||||
std::shared_ptr<unsigned char> 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) {
|
||||
throw osmium::pbf_error(std::string("invalid blob size: " + std::to_string(size)));
|
||||
}
|
||||
if (! input_queue_reader(m_input_buffer.get(), static_cast<size_t>(size))) {
|
||||
throw osmium::pbf_error("truncated data (EOF encountered)");
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void doit() {
|
||||
OSMPBF::Blob pbf_blob;
|
||||
if (!pbf_blob.ParseFromArray(m_input_buffer.get(), m_size)) {
|
||||
throw osmium::pbf_error("failed to parse blob");
|
||||
}
|
||||
|
||||
if (pbf_blob.has_raw()) {
|
||||
static_cast<TDerived*>(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<unsigned long>(raw_size)) };
|
||||
static_cast<TDerived*>(this)->handle_blob(unpack_buffer);
|
||||
return;
|
||||
} else if (pbf_blob.has_lzma_data()) {
|
||||
throw osmium::pbf_error("lzma blobs not implemented");
|
||||
} else {
|
||||
throw osmium::pbf_error("blob contains no data");
|
||||
}
|
||||
}
|
||||
|
||||
osmium::memory::Buffer operator()() {
|
||||
OSMPBF::Blob pbf_blob;
|
||||
if (!pbf_blob.ParseFromArray(m_input_buffer.get(), m_size)) {
|
||||
throw osmium::pbf_error("failed to parse blob");
|
||||
}
|
||||
|
||||
if (pbf_blob.has_raw()) {
|
||||
return static_cast<TDerived*>(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<unsigned long>(raw_size)) };
|
||||
return static_cast<TDerived*>(this)->handle_blob(unpack_buffer);
|
||||
} else if (pbf_blob.has_lzma_data()) {
|
||||
throw osmium::pbf_error("lzma blobs not implemented");
|
||||
} else {
|
||||
throw osmium::pbf_error("blob contains no data");
|
||||
}
|
||||
}
|
||||
|
||||
}; // class BlobParser;
|
||||
|
||||
class HeaderBlobParser : public BlobParser<HeaderBlobParser> {
|
||||
|
||||
osmium::io::Header& m_header;
|
||||
|
||||
void handle_blob(const std::string& data) {
|
||||
OSMPBF::HeaderBlock pbf_header_block;
|
||||
if (!pbf_header_block.ParseFromArray(data.data(), static_cast_with_assert<int>(data.size()))) {
|
||||
throw osmium::pbf_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.set_has_multiple_object_versions(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw osmium::pbf_error(std::string("required feature not supported: ") + feature);
|
||||
}
|
||||
|
||||
for (int i=0; i < pbf_header_block.optional_features_size(); ++i) {
|
||||
const std::string& feature = pbf_header_block.optional_features(i);
|
||||
m_header.set("pbf_optional_feature_" + std::to_string(i), feature);
|
||||
}
|
||||
|
||||
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>;
|
||||
|
||||
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<DataBlobParser> {
|
||||
|
||||
osmium::osm_entity_bits::type m_read_types;
|
||||
|
||||
osmium::memory::Buffer handle_blob(const std::string& data) {
|
||||
PBFPrimitiveBlockParser parser(data.data(), static_cast_with_assert<int>(data.size()), m_read_types);
|
||||
return std::move(parser());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
friend class BlobParser<DataBlobParser>;
|
||||
|
||||
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.
|
||||
*/
|
||||
@@ -549,25 +85,50 @@ namespace osmium {
|
||||
|
||||
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<bool> m_done;
|
||||
std::thread m_reader;
|
||||
OSMPBF::BlobHeader m_blob_header;
|
||||
InputQueueReader m_input_queue_reader;
|
||||
osmium::thread::Queue<std::string>& m_input_queue;
|
||||
std::string m_input_buffer;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Read the given number of bytes from the input queue.
|
||||
*
|
||||
* @param expected_type Expected type of data ("OSMHeader" or "OSMData").
|
||||
* @param size Number of bytes to read
|
||||
* @returns String with the data
|
||||
* @throws osmium::pbf_error If size bytes can't be read
|
||||
*/
|
||||
std::string read_from_input_queue(size_t size) {
|
||||
while (m_input_buffer.size() < size) {
|
||||
std::string new_data;
|
||||
m_input_queue.wait_and_pop(new_data);
|
||||
if (new_data.empty()) {
|
||||
throw osmium::pbf_error("truncated data (EOF encountered)");
|
||||
}
|
||||
m_input_buffer += new_data;
|
||||
}
|
||||
|
||||
std::string output { m_input_buffer.substr(size) };
|
||||
m_input_buffer.resize(size);
|
||||
std::swap(output, m_input_buffer);
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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").
|
||||
* @returns Size of the data read from BlobHeader (0 on EOF).
|
||||
*/
|
||||
int read_blob_header(const char* expected_type) {
|
||||
size_t read_blob_header(const char* expected_type) {
|
||||
uint32_t size_in_network_byte_order;
|
||||
|
||||
if (! m_input_queue_reader(reinterpret_cast<unsigned char*>(&size_in_network_byte_order), sizeof(size_in_network_byte_order))) {
|
||||
try {
|
||||
std::string input_data = read_from_input_queue(sizeof(size_in_network_byte_order));
|
||||
size_in_network_byte_order = *reinterpret_cast<const uint32_t*>(input_data.data());
|
||||
} catch (osmium::pbf_error&) {
|
||||
return 0; // EOF
|
||||
}
|
||||
|
||||
@@ -576,47 +137,33 @@ namespace osmium {
|
||||
throw osmium::pbf_error("invalid BlobHeader size (> max_blob_header_size)");
|
||||
}
|
||||
|
||||
unsigned char blob_header_buffer[OSMPBF::max_blob_header_size];
|
||||
if (! m_input_queue_reader(blob_header_buffer, size)) {
|
||||
throw osmium::pbf_error("read error");
|
||||
}
|
||||
|
||||
if (!m_blob_header.ParseFromArray(blob_header_buffer, static_cast<int>(size))) {
|
||||
OSMPBF::BlobHeader blob_header;
|
||||
if (!blob_header.ParseFromString(read_from_input_queue(size))) {
|
||||
throw osmium::pbf_error("failed to parse BlobHeader");
|
||||
}
|
||||
|
||||
if (std::strcmp(m_blob_header.type().c_str(), expected_type)) {
|
||||
if (blob_header.type() != expected_type) {
|
||||
throw osmium::pbf_error("blob does not have expected type (OSMHeader in first blob, OSMData in following blobs)");
|
||||
}
|
||||
|
||||
return m_blob_header.datasize();
|
||||
return static_cast<size_t>(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 (int size = read_blob_header("OSMData")) {
|
||||
DataBlobParser data_blob_parser(size, n, m_input_queue_reader, read_types);
|
||||
while (auto size = read_blob_header("OSMData")) {
|
||||
|
||||
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));
|
||||
}
|
||||
m_queue.push(osmium::thread::Pool::instance().submit(DataBlobParser{read_from_input_queue(size), read_types}));
|
||||
} else {
|
||||
std::promise<osmium::memory::Buffer> promise;
|
||||
m_queue.push(promise.get_future());
|
||||
DataBlobParser data_blob_parser{read_from_input_queue(size), read_types};
|
||||
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;
|
||||
}
|
||||
@@ -635,21 +182,16 @@ namespace osmium {
|
||||
*/
|
||||
PBFInputFormat(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue<std::string>& 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_use_thread_pool(osmium::config::use_pool_threads_for_pbf_parsing()),
|
||||
m_queue(20, "pbf_parser_results"), // XXX
|
||||
m_done(false),
|
||||
m_input_queue_reader(input_queue) {
|
||||
m_input_queue(input_queue),
|
||||
m_input_buffer() {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
// handle OSMHeader
|
||||
int size = read_blob_header("OSMHeader");
|
||||
|
||||
{
|
||||
HeaderBlobParser header_blob_parser(size, m_input_queue_reader, m_header);
|
||||
header_blob_parser.doit();
|
||||
}
|
||||
auto size = read_blob_header("OSMHeader");
|
||||
m_header = parse_header_blob(read_from_input_queue(size));
|
||||
|
||||
if (m_read_which_entities != osmium::osm_entity_bits::nothing) {
|
||||
m_reader = std::thread(&PBFInputFormat::parse_osm_data, this, m_read_which_entities);
|
||||
|
||||
@@ -527,9 +527,6 @@ namespace osmium {
|
||||
std::promise<std::string> 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();
|
||||
|
||||
+449
@@ -0,0 +1,449 @@
|
||||
#ifndef OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP
|
||||
#define OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> 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 <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
|
||||
#include <osmpbf/osmpbf.h>
|
||||
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/io/detail/pbf.hpp> // IWYU pragma: export
|
||||
#include <osmium/io/detail/zlib.hpp>
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/entity_bits.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace io {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class PBFPrimitiveBlockParser {
|
||||
|
||||
static constexpr size_t initial_buffer_size = 2 * 1024 * 1024;
|
||||
|
||||
const std::string& m_data;
|
||||
|
||||
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 std::string& data, osmium::osm_entity_bits::type read_types) :
|
||||
m_data(data),
|
||||
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.ParseFromString(m_data)) {
|
||||
throw osmium::pbf_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 osmium::pbf_error("group of unknown type");
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(m_buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <class TBuilder, class TPBFObject>
|
||||
void parse_attributes(TBuilder& builder, const TPBFObject& pbf_object) {
|
||||
auto& object = builder.object();
|
||||
|
||||
object.set_id(pbf_object.id());
|
||||
|
||||
if (pbf_object.has_info()) {
|
||||
object.set_version(static_cast_with_assert<object_version_type>(pbf_object.info().version()))
|
||||
.set_changeset(static_cast_with_assert<changeset_id_type>(pbf_object.info().changeset()))
|
||||
.set_timestamp(pbf_object.info().timestamp() * m_date_factor)
|
||||
.set_uid_from_signed(pbf_object.info().uid());
|
||||
if (pbf_object.info().has_visible()) {
|
||||
object.set_visible(pbf_object.info().visible());
|
||||
}
|
||||
builder.add_user(m_stringtable->s(static_cast_with_assert<int>(pbf_object.info().user_sid())));
|
||||
} else {
|
||||
builder.add_user("", 1);
|
||||
}
|
||||
}
|
||||
|
||||
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().set_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<int>(pbf_node.keys(tag))),
|
||||
m_stringtable->s(static_cast<int>(pbf_node.vals(tag))));
|
||||
}
|
||||
}
|
||||
|
||||
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<int>(pbf_way.keys(tag))),
|
||||
m_stringtable->s(static_cast<int>(pbf_way.vals(tag))));
|
||||
}
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
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<int>(pbf_relation.keys(tag))),
|
||||
m_stringtable->s(static_cast<int>(pbf_relation.vals(tag))));
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
m_stringtable->s(dense.keys_vals(n)));
|
||||
|
||||
++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.set_id(last_dense_id);
|
||||
|
||||
if (dense.has_denseinfo()) {
|
||||
auto v = dense.denseinfo().version(i);
|
||||
assert(v > 0);
|
||||
node.set_version(static_cast<osmium::object_version_type>(v));
|
||||
node.set_changeset(static_cast<osmium::changeset_id_type>(last_dense_changeset));
|
||||
node.set_timestamp(last_dense_timestamp * m_date_factor);
|
||||
node.set_uid_from_signed(static_cast<osmium::signed_user_id_type>(last_dense_uid));
|
||||
node.set_visible(visible);
|
||||
builder.add_user(m_stringtable->s(static_cast<int>(last_dense_user_sid)));
|
||||
} else {
|
||||
builder.add_user("", 1);
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
builder.object().set_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
|
||||
|
||||
/**
|
||||
* PBF blobs can optionally be packed with the zlib algorithm.
|
||||
* This function returns the raw data (if it was unpacked) or
|
||||
* the unpacked data (if it was packed).
|
||||
*
|
||||
* @param input_data Reference to input data.
|
||||
* @returns Unpacked data
|
||||
* @throws osmium::pbf_error If there was a problem parsing the PBF
|
||||
*/
|
||||
inline std::unique_ptr<const std::string> unpack_blob(const std::string& input_data) {
|
||||
OSMPBF::Blob pbf_blob;
|
||||
if (!pbf_blob.ParseFromString(input_data)) {
|
||||
throw osmium::pbf_error("failed to parse blob");
|
||||
}
|
||||
|
||||
if (pbf_blob.has_raw()) {
|
||||
return std::unique_ptr<std::string>(pbf_blob.release_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);
|
||||
return osmium::io::detail::zlib_uncompress(pbf_blob.zlib_data(), static_cast<unsigned long>(raw_size));
|
||||
} else if (pbf_blob.has_lzma_data()) {
|
||||
throw osmium::pbf_error("lzma blobs not implemented");
|
||||
} else {
|
||||
throw osmium::pbf_error("blob contains no data");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse blob as a HeaderBlock.
|
||||
*
|
||||
* @param input_buffer Blob data
|
||||
* @returns Header object
|
||||
* @throws osmium::pbf_error If there was a parsing error
|
||||
*/
|
||||
inline osmium::io::Header parse_header_blob(const std::string& input_buffer) {
|
||||
const std::unique_ptr<const std::string> data = unpack_blob(input_buffer);
|
||||
|
||||
OSMPBF::HeaderBlock pbf_header_block;
|
||||
if (!pbf_header_block.ParseFromString(*data)) {
|
||||
throw osmium::pbf_error("failed to parse HeaderBlock");
|
||||
}
|
||||
|
||||
osmium::io::Header header;
|
||||
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") {
|
||||
header.set("pbf_dense_nodes", true);
|
||||
continue;
|
||||
}
|
||||
if (feature == "HistoricalInformation") {
|
||||
header.set_has_multiple_object_versions(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw osmium::pbf_error(std::string("required feature not supported: ") + feature);
|
||||
}
|
||||
|
||||
for (int i=0; i < pbf_header_block.optional_features_size(); ++i) {
|
||||
const std::string& feature = pbf_header_block.optional_features(i);
|
||||
header.set("pbf_optional_feature_" + std::to_string(i), feature);
|
||||
}
|
||||
|
||||
if (pbf_header_block.has_writingprogram()) {
|
||||
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));
|
||||
header.add_box(box);
|
||||
}
|
||||
|
||||
if (pbf_header_block.has_osmosis_replication_timestamp()) {
|
||||
header.set("osmosis_replication_timestamp", osmium::Timestamp(pbf_header_block.osmosis_replication_timestamp()).to_iso());
|
||||
}
|
||||
|
||||
if (pbf_header_block.has_osmosis_replication_sequence_number()) {
|
||||
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()) {
|
||||
header.set("osmosis_replication_base_url", pbf_header_block.osmosis_replication_base_url());
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
class DataBlobParser {
|
||||
|
||||
std::string m_input_buffer;
|
||||
osmium::osm_entity_bits::type m_read_types;
|
||||
|
||||
public:
|
||||
|
||||
DataBlobParser(std::string&& input_buffer, osmium::osm_entity_bits::type read_types) :
|
||||
m_input_buffer(std::move(input_buffer)),
|
||||
m_read_types(read_types) {
|
||||
if (input_buffer.size() > OSMPBF::max_uncompressed_blob_size) {
|
||||
throw osmium::pbf_error(std::string("invalid blob size: " + std::to_string(input_buffer.size())));
|
||||
}
|
||||
}
|
||||
|
||||
DataBlobParser(const DataBlobParser& other) :
|
||||
m_input_buffer(std::move(other.m_input_buffer)),
|
||||
m_read_types(other.m_read_types) {
|
||||
}
|
||||
|
||||
DataBlobParser& operator=(const DataBlobParser&) = delete;
|
||||
|
||||
osmium::memory::Buffer operator()() {
|
||||
const std::unique_ptr<const std::string> data = unpack_blob(m_input_buffer);
|
||||
PBFPrimitiveBlockParser parser(*data, m_read_types);
|
||||
return std::move(parser());
|
||||
}
|
||||
|
||||
}; // class DataBlobParser
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_DETAIL_PBF_PRIMITIVE_BLOCK_PARSER_HPP
|
||||
+1
-1
@@ -41,8 +41,8 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/io/compression.hpp>
|
||||
#include <osmium/thread/name.hpp>
|
||||
#include <osmium/thread/queue.hpp>
|
||||
#include <osmium/thread/util.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include <osmium/io/compression.hpp>
|
||||
#include <osmium/io/detail/output_format.hpp>
|
||||
#include <osmium/thread/name.hpp>
|
||||
#include <osmium/thread/util.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
|
||||
+11
-18
@@ -57,6 +57,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/builder/builder.hpp>
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/io/detail/input_format.hpp>
|
||||
#include <osmium/io/error.hpp>
|
||||
#include <osmium/io/file_format.hpp>
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
@@ -68,7 +69,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/osm/object.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/thread/queue.hpp>
|
||||
#include <osmium/thread/checked_task.hpp>
|
||||
#include <osmium/thread/util.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
|
||||
namespace osmium {
|
||||
@@ -178,8 +179,6 @@ namespace osmium {
|
||||
|
||||
osmium::osm_entity_bits::type m_read_types;
|
||||
|
||||
size_t m_max_queue_size;
|
||||
|
||||
std::atomic<bool>& m_done;
|
||||
|
||||
/**
|
||||
@@ -270,7 +269,6 @@ namespace osmium {
|
||||
m_queue(queue),
|
||||
m_header_promise(header_promise),
|
||||
m_read_types(read_types),
|
||||
m_max_queue_size(100),
|
||||
m_done(done) {
|
||||
}
|
||||
|
||||
@@ -297,15 +295,14 @@ namespace osmium {
|
||||
m_queue(other.m_queue),
|
||||
m_header_promise(other.m_header_promise),
|
||||
m_read_types(other.m_read_types),
|
||||
m_max_queue_size(100),
|
||||
m_done(other.m_done) {
|
||||
}
|
||||
|
||||
XMLParser(XMLParser&& other) = default;
|
||||
XMLParser(XMLParser&&) = default;
|
||||
|
||||
XMLParser& operator=(const XMLParser&) = delete;
|
||||
|
||||
XMLParser& operator=(XMLParser&& other) = default;
|
||||
XMLParser& operator=(XMLParser&&) = default;
|
||||
|
||||
~XMLParser() = default;
|
||||
|
||||
@@ -650,10 +647,6 @@ namespace osmium {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,12 +654,12 @@ namespace osmium {
|
||||
|
||||
class XMLInputFormat : public osmium::io::detail::InputFormat {
|
||||
|
||||
static constexpr size_t m_max_queue_size = 100;
|
||||
static constexpr size_t max_queue_size = 100;
|
||||
|
||||
osmium::thread::Queue<osmium::memory::Buffer> m_queue;
|
||||
std::atomic<bool> m_done;
|
||||
std::promise<osmium::io::Header> m_header_promise;
|
||||
osmium::thread::CheckedTask<XMLParser> m_parser_task;
|
||||
std::future<bool> m_parser_future;
|
||||
|
||||
public:
|
||||
|
||||
@@ -679,10 +672,10 @@ namespace osmium {
|
||||
*/
|
||||
explicit XMLInputFormat(const osmium::io::File& file, osmium::osm_entity_bits::type read_which_entities, osmium::thread::Queue<std::string>& input_queue) :
|
||||
osmium::io::detail::InputFormat(file, read_which_entities, input_queue),
|
||||
m_queue(),
|
||||
m_queue(max_queue_size, "xml_parser_results"),
|
||||
m_done(false),
|
||||
m_header_promise(),
|
||||
m_parser_task(input_queue, m_queue, m_header_promise, read_which_entities, m_done) {
|
||||
m_parser_future(std::async(std::launch::async, XMLParser(input_queue, m_queue, m_header_promise, read_which_entities, m_done))) {
|
||||
}
|
||||
|
||||
~XMLInputFormat() {
|
||||
@@ -694,7 +687,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
virtual osmium::io::Header header() override final {
|
||||
m_parser_task.check_for_exception();
|
||||
osmium::thread::check_for_exception(m_parser_future);
|
||||
return m_header_promise.get_future().get();
|
||||
}
|
||||
|
||||
@@ -704,13 +697,13 @@ namespace osmium {
|
||||
m_queue.wait_and_pop(buffer);
|
||||
}
|
||||
|
||||
m_parser_task.check_for_exception();
|
||||
osmium::thread::check_for_exception(m_parser_future);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void close() {
|
||||
m_done = true;
|
||||
m_parser_task.close();
|
||||
osmium::thread::wait_until_done(m_parser_future);
|
||||
}
|
||||
|
||||
}; // class XMLInputFormat
|
||||
|
||||
+3
-7
@@ -233,8 +233,8 @@ namespace osmium {
|
||||
XMLOutputBlock(const XMLOutputBlock&) = delete;
|
||||
XMLOutputBlock& operator=(const XMLOutputBlock&) = delete;
|
||||
|
||||
XMLOutputBlock(XMLOutputBlock&& other) = default;
|
||||
XMLOutputBlock& operator=(XMLOutputBlock&& other) = default;
|
||||
XMLOutputBlock(XMLOutputBlock&&) = default;
|
||||
XMLOutputBlock& operator=(XMLOutputBlock&&) = default;
|
||||
|
||||
std::string operator()() {
|
||||
osmium::apply(m_input_buffer.cbegin(), m_input_buffer.cend(), *this);
|
||||
@@ -405,11 +405,7 @@ namespace osmium {
|
||||
}
|
||||
|
||||
void write_buffer(osmium::memory::Buffer&& buffer) override final {
|
||||
osmium::thread::SharedPtrWrapper<XMLOutputBlock> output_block(std::move(buffer), m_write_visible_flag, m_file.is_true("xml_change_format"));
|
||||
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
|
||||
}
|
||||
m_output_queue.push(osmium::thread::Pool::instance().submit(XMLOutputBlock{std::move(buffer), m_write_visible_flag, m_file.is_true("xml_change_format")}));
|
||||
}
|
||||
|
||||
void write_header(const osmium::io::Header& header) override final {
|
||||
|
||||
+4
-3
@@ -35,6 +35,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#define OSMIUM_LINK_WITH_LIBS_ZLIB -lz
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
@@ -76,10 +77,10 @@ namespace osmium {
|
||||
* @param raw_size Size of uncompressed data.
|
||||
* @returns Uncompressed data.
|
||||
*/
|
||||
inline std::string zlib_uncompress(const std::string& input, unsigned long raw_size) {
|
||||
std::string output(raw_size, '\0');
|
||||
inline std::unique_ptr<std::string> zlib_uncompress(const std::string& input, unsigned long raw_size) {
|
||||
auto output = std::unique_ptr<std::string>(new std::string(raw_size, '\0'));
|
||||
|
||||
if (::uncompress(reinterpret_cast<unsigned char*>(const_cast<char *>(output.data())),
|
||||
if (::uncompress(reinterpret_cast<unsigned char*>(const_cast<char *>(output->data())),
|
||||
&raw_size,
|
||||
reinterpret_cast<const unsigned char*>(input.data()),
|
||||
input.size()) != Z_OK) {
|
||||
|
||||
Vendored
+57
@@ -0,0 +1,57 @@
|
||||
#ifndef OSMIUM_IO_ERROR_HPP
|
||||
#define OSMIUM_IO_ERROR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013,2014 Jochen Topf <jochen@topf.org> 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 <stdexcept>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* Exception thrown when some kind of input/output operation failed.
|
||||
*/
|
||||
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
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_IO_ERROR_HPP
|
||||
Vendored
+4
-19
@@ -45,21 +45,6 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* Exception thrown when some kind of input/output operation failed.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@@ -162,11 +147,11 @@ namespace osmium {
|
||||
}
|
||||
}
|
||||
|
||||
File(const File& other) = default;
|
||||
File& operator=(const File& other) = default;
|
||||
File(const File&) = default;
|
||||
File& operator=(const File&) = default;
|
||||
|
||||
File(File&& other) = default;
|
||||
File& operator=(File&& other) = default;
|
||||
File(File&&) = default;
|
||||
File& operator=(File&&) = default;
|
||||
|
||||
~File() = default;
|
||||
|
||||
|
||||
Vendored
+52
-52
@@ -1,52 +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 <jochen@topf.org> 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
|
||||
#ifndef OSMIUM_IO_OVERWRITE_HPP
|
||||
#define OSMIUM_IO_OVERWRITE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2014 Jochen Topf <jochen@topf.org> 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
|
||||
|
||||
Vendored
+7
-8
@@ -59,8 +59,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/entity_bits.hpp>
|
||||
#include <osmium/thread/checked_task.hpp>
|
||||
#include <osmium/thread/name.hpp>
|
||||
#include <osmium/thread/util.hpp>
|
||||
#include <osmium/thread/queue.hpp>
|
||||
|
||||
namespace osmium {
|
||||
@@ -83,7 +82,7 @@ namespace osmium {
|
||||
osmium::thread::Queue<std::string> m_input_queue;
|
||||
|
||||
std::unique_ptr<osmium::io::Decompressor> m_decompressor;
|
||||
osmium::thread::CheckedTask<detail::ReadThread> m_read_task;
|
||||
std::future<bool> m_read_future;
|
||||
|
||||
std::unique_ptr<osmium::io::detail::InputFormat> m_input;
|
||||
|
||||
@@ -173,11 +172,11 @@ namespace osmium {
|
||||
m_read_which_entities(read_which_entities),
|
||||
m_input_done(false),
|
||||
m_childpid(0),
|
||||
m_input_queue(),
|
||||
m_input_queue(20, "raw_input"), // XXX
|
||||
m_decompressor(m_file.buffer() ?
|
||||
osmium::io::CompressionFactory::instance().create_decompressor(file.compression(), m_file.buffer(), m_file.buffer_size()) :
|
||||
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_read_future(std::async(std::launch::async, detail::ReadThread(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)) {
|
||||
}
|
||||
|
||||
@@ -228,7 +227,7 @@ namespace osmium {
|
||||
}
|
||||
#endif
|
||||
|
||||
m_read_task.close();
|
||||
osmium::thread::wait_until_done(m_read_future);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,7 +250,7 @@ namespace osmium {
|
||||
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();
|
||||
osmium::thread::check_for_exception(m_read_future);
|
||||
|
||||
if (m_read_which_entities == osmium::osm_entity_bits::nothing || m_input_done) {
|
||||
// If the caller didn't want anything but the header, it will
|
||||
@@ -270,7 +269,7 @@ namespace osmium {
|
||||
* Has the end of file been reached? This is set after the last
|
||||
* data has been read. It is also set by calling close().
|
||||
*/
|
||||
bool eof() {
|
||||
bool eof() const {
|
||||
return m_input_done;
|
||||
}
|
||||
|
||||
|
||||
+51
-51
@@ -1,51 +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 <jochen@topf.org> 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 <osmium/io/reader.hpp>
|
||||
#include <osmium/io/input_iterator.hpp>
|
||||
|
||||
namespace std {
|
||||
|
||||
inline osmium::io::InputIterator<osmium::io::Reader> begin(osmium::io::Reader& reader) {
|
||||
return osmium::io::InputIterator<osmium::io::Reader>(reader);
|
||||
}
|
||||
|
||||
inline osmium::io::InputIterator<osmium::io::Reader> end(osmium::io::Reader&) {
|
||||
return osmium::io::InputIterator<osmium::io::Reader>();
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // OSMIUM_IO_READER_ITERATOR_HPP
|
||||
#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 <jochen@topf.org> 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 <osmium/io/reader.hpp>
|
||||
#include <osmium/io/input_iterator.hpp>
|
||||
|
||||
namespace std {
|
||||
|
||||
inline osmium::io::InputIterator<osmium::io::Reader> begin(osmium::io::Reader& reader) {
|
||||
return osmium::io::InputIterator<osmium::io::Reader>(reader);
|
||||
}
|
||||
|
||||
inline osmium::io::InputIterator<osmium::io::Reader> end(osmium::io::Reader&) {
|
||||
return osmium::io::InputIterator<osmium::io::Reader>();
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // OSMIUM_IO_READER_ITERATOR_HPP
|
||||
|
||||
Vendored
+8
-6
@@ -45,7 +45,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/io/header.hpp>
|
||||
#include <osmium/io/overwrite.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/thread/checked_task.hpp>
|
||||
#include <osmium/thread/util.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
@@ -61,12 +61,13 @@ namespace osmium {
|
||||
|
||||
osmium::io::File m_file;
|
||||
|
||||
std::unique_ptr<osmium::io::detail::OutputFormat> m_output;
|
||||
osmium::io::detail::data_queue_type m_output_queue;
|
||||
|
||||
std::unique_ptr<osmium::io::detail::OutputFormat> m_output;
|
||||
|
||||
std::unique_ptr<osmium::io::Compressor> m_compressor;
|
||||
|
||||
osmium::thread::CheckedTask<detail::WriteThread> m_write_task;
|
||||
std::future<bool> m_write_future;
|
||||
|
||||
public:
|
||||
|
||||
@@ -87,9 +88,10 @@ namespace osmium {
|
||||
*/
|
||||
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_queue(20, "raw_output"), // XXX
|
||||
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_write_future(std::async(std::launch::async, detail::WriteThread(m_output_queue, m_compressor.get()))) {
|
||||
assert(!m_file.buffer());
|
||||
m_output->write_header(header);
|
||||
}
|
||||
@@ -115,7 +117,7 @@ namespace osmium {
|
||||
* @throws Some form of std::runtime_error when there is a problem.
|
||||
*/
|
||||
void operator()(osmium::memory::Buffer&& buffer) {
|
||||
m_write_task.check_for_exception();
|
||||
osmium::thread::check_for_exception(m_write_future);
|
||||
if (buffer.committed() > 0) {
|
||||
m_output->write_buffer(std::move(buffer));
|
||||
}
|
||||
@@ -131,7 +133,7 @@ namespace osmium {
|
||||
*/
|
||||
void close() {
|
||||
m_output->close();
|
||||
m_write_task.close();
|
||||
osmium::thread::wait_until_done(m_write_future);
|
||||
}
|
||||
|
||||
}; // class Writer
|
||||
|
||||
Reference in New Issue
Block a user