libosmium version bump

This commit is contained in:
Dennis Luxen 2014-10-29 16:27:48 -04:00
parent 0249bed53a
commit 710e74219a
91 changed files with 7244 additions and 6417 deletions

View File

@ -152,15 +152,26 @@ namespace osmium {
}
}
struct MPFilter : public osmium::tags::KeyFilter {
MPFilter() : osmium::tags::KeyFilter(true) {
add(false, "type");
add(false, "created_by");
add(false, "source");
add(false, "note");
add(false, "test:id");
add(false, "test:section");
}
}; // struct MPFilter
static MPFilter& filter() {
static MPFilter filter;
return filter;
}
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);
auto count = std::count_if(relation.tags().begin(), relation.tags().end(), filter());
if (debug()) {
std::cerr << " found " << count << " tags on relation (without ignored ones)\n";
@ -728,27 +739,26 @@ namespace osmium {
const osmium::TagList& area_tags = out_buffer.get<osmium::Area>(area_offset).tags(); // tags of the area we just built
// Find all closed ways that are inner rings and check their
// tags. If they are not the same as the tags of the area we
// just built, add them to a list and later build areas for
// them, too.
std::vector<const osmium::Way*> ways_that_should_be_areas;
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<const osmium::Way>(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);
auto d = std::count_if(way.tags().begin(), way.tags().end(), filter());
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());
osmium::tags::KeyFilter::iterator way_fi_begin(filter(), way.tags().begin(), way.tags().end());
osmium::tags::KeyFilter::iterator way_fi_end(filter(), way.tags().end(), way.tags().end());
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);
if (!std::equal(way_fi_begin, way_fi_end, area_fi_begin) || d != std::distance(area_fi_begin, area_fi_end)) {
ways_that_should_be_areas.push_back(&way);
}
}
}
@ -756,6 +766,12 @@ namespace osmium {
++memit;
}
}
// Now build areas for all ways found in the last step.
for (const osmium::Way* way : ways_that_should_be_areas) {
Assembler assembler(m_config);
assembler(*way, out_buffer);
}
}
}; // class Assembler

View File

@ -78,7 +78,7 @@ namespace osmium {
swap(m_first, m_second);
}
explicit NodeRefSegment() :
explicit NodeRefSegment() noexcept :
m_first(),
m_second(),
m_role(nullptr),
@ -104,12 +104,12 @@ namespace osmium {
~NodeRefSegment() = default;
/// Return first NodeRef of Segment according to sorting order (bottom left to top right).
const osmium::NodeRef& first() const {
const osmium::NodeRef& first() const noexcept {
return m_first;
}
/// Return second NodeRef of Segment according to sorting order (bottom left to top right).
const osmium::NodeRef& second() const {
const osmium::NodeRef& second() const noexcept {
return m_second;
}
@ -138,26 +138,26 @@ namespace osmium {
return ((bx - ax)*(ly - ay) - (by - ay)*(lx - ax)) <= 0;
}
bool role_outer() const {
bool role_outer() const noexcept {
return !strcmp(m_role, "outer");
}
bool role_inner() const {
bool role_inner() const noexcept {
return !strcmp(m_role, "inner");
}
const osmium::Way* way() const {
const osmium::Way* way() const noexcept {
return m_way;
}
}; // class NodeRefSegment
/// NodeRefSegments are equal if both their locations are equal
inline bool operator==(const NodeRefSegment& lhs, const NodeRefSegment& rhs) {
inline bool operator==(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
return lhs.first().location() == rhs.first().location() && lhs.second().location() == rhs.second().location();
}
inline bool operator!=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) {
inline bool operator!=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
return ! (lhs == rhs);
}
@ -166,19 +166,19 @@ namespace osmium {
* 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) {
inline bool operator<(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
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) {
inline bool operator>(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
return rhs < lhs;
}
inline bool operator<=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) {
inline bool operator<=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
return ! (rhs < lhs);
}
inline bool operator>=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) {
inline bool operator>=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
return ! (lhs < rhs);
}
@ -187,7 +187,7 @@ namespace osmium {
return out << segment.first() << "--" << segment.second();
}
inline bool outside_x_range(const NodeRefSegment& s1, const NodeRefSegment& s2) {
inline bool outside_x_range(const NodeRefSegment& s1, const NodeRefSegment& s2) noexcept {
if (s1.first().location().x() > s2.second().location().x()) {
return true;
}
@ -204,20 +204,20 @@ namespace osmium {
}
/**
* 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.
*/
* 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() ||
@ -226,10 +226,15 @@ namespace osmium {
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()));
auto d = (static_cast<int64_t>(s2.second().y()) - static_cast<int64_t>(s2.first().y())) *
(static_cast<int64_t>(s1.second().x()) - static_cast<int64_t>(s1.first().x())) -
(static_cast<int64_t>(s2.second().x()) - static_cast<int64_t>(s2.first().x())) *
(static_cast<int64_t>(s1.second().y()) - static_cast<int64_t>(s1.first().y()));
if (d != 0) {
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()));

View File

@ -70,7 +70,7 @@ namespace osmium {
public:
explicit ProtoRing(const NodeRefSegment& segment) :
explicit ProtoRing(const NodeRefSegment& segment) noexcept :
m_segments() {
add_segment_back(segment);
}
@ -80,19 +80,19 @@ namespace osmium {
std::copy(sbegin, send, m_segments.begin());
}
bool outer() const {
bool outer() const noexcept {
return m_outer;
}
void set_inner() {
void set_inner() noexcept {
m_outer = false;
}
segments_type& segments() {
segments_type& segments() noexcept {
return m_segments;
}
const segments_type& segments() const {
const segments_type& segments() const noexcept {
return m_segments;
}

View File

@ -64,7 +64,7 @@ namespace osmium {
public:
explicit SegmentList(bool debug) :
explicit SegmentList(bool debug) noexcept :
m_debug(debug) {
}
@ -77,21 +77,21 @@ namespace osmium {
SegmentList& operator=(SegmentList&& other) = delete;
/// The number of segments in the list.
size_t size() const {
size_t size() const noexcept {
return m_segments.size();
}
bool empty() const {
bool empty() const noexcept {
return m_segments.empty();
}
typedef slist_type::const_iterator const_iterator;
const_iterator begin() const {
const_iterator begin() const noexcept {
return m_segments.begin();
}
const_iterator end() const {
const_iterator end() const noexcept {
return m_segments.end();
}
@ -99,7 +99,7 @@ namespace osmium {
* Enable or disable debug output to stderr. This is for Osmium
* developers only.
*/
void enable_debug_output(bool debug=true) {
void enable_debug_output(bool debug=true) noexcept {
m_debug = debug;
}

View File

@ -1,211 +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 <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 <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <vector>
#include <osmium/memory/buffer.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/relation.hpp>
#include <osmium/osm/tag.hpp>
#include <osmium/osm/way.hpp>
#include <osmium/relations/collector.hpp>
#include <osmium/relations/detail/member_meta.hpp>
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 TAssembler>
class MultipolygonCollector : public osmium::relations::Collector<MultipolygonCollector<TAssembler>, false, true, false> {
typedef typename osmium::relations::Collector<MultipolygonCollector<TAssembler>, 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<size_t> 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
#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 <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 <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <vector>
#include <osmium/memory/buffer.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/relation.hpp>
#include <osmium/osm/tag.hpp>
#include <osmium/osm/way.hpp>
#include <osmium/relations/collector.hpp>
#include <osmium/relations/detail/member_meta.hpp>
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 TAssembler>
class MultipolygonCollector : public osmium::relations::Collector<MultipolygonCollector<TAssembler>, false, true, false> {
typedef typename osmium::relations::Collector<MultipolygonCollector<TAssembler>, 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<size_t> 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 (osmium::relations::count_not_removed(range.first, range.second) == 1) {
this->get_member(range.first->buffer_offset()).set_removed(true);
}
for (auto it = range.first; it != range.second; ++it) {
if (!it->removed() && relation.id() == this->get_relation(it->relation_pos()).id()) {
it->remove();
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

View File

@ -1,149 +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 <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/osm/item_type.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/types.hpp>
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
#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 <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/osm/item_type.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/types.hpp>
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) noexcept {
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

View File

@ -37,10 +37,14 @@ DEALINGS IN THE SOFTWARE.
#define OSMIUM_LINK_WITH_LIBS_OGR `gdal-config --libs`
#pragma GCC diagnostic push
#ifdef __clang__
# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"
#endif
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wpadded"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"
# include <ogr_api.h>
# include <ogrsf_frmts.h>
#pragma GCC diagnostic pop

View File

@ -1,96 +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 <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 <ostream>
#include <osmium/area/problem_reporter.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/types.hpp>
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
#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 <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 <ostream>
#include <osmium/area/problem_reporter.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/types.hpp>
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

View File

@ -1,179 +1,220 @@
#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 <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 <cstring>
#include <new>
#include <osmium/memory/buffer.hpp>
#include <osmium/memory/item.hpp>
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<osmium::memory::Item*>(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 <class T>
T* reserve_space_for() {
assert(m_buffer.is_aligned());
return reinterpret_cast<T*>(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 T>
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<T&>(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
#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 <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 <cstring>
#include <new>
#include <type_traits>
#include <osmium/memory/buffer.hpp>
#include <osmium/memory/item.hpp>
#include <osmium/osm/types.hpp>
#include <osmium/util/cast.hpp>
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, osmium::memory::item_size_type 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<osmium::memory::Item*>(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) {
auto 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 noexcept {
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 <class T>
T* reserve_space_for() {
assert(m_buffer.is_aligned());
return reinterpret_cast<T*>(m_buffer.reserve_space(sizeof(T)));
}
/**
* Append data to buffer.
*
* @param data Pointer to data.
* @param length Length of data in bytes. If data is a
* \0-terminated string, length must contain the
* \0 byte.
*/
osmium::memory::item_size_type append(const char* data, const osmium::memory::item_size_type length) {
std::memcpy(m_buffer.reserve_space(length), data, length);
return length;
}
/**
* Append \0-terminated string to buffer.
*/
osmium::memory::item_size_type append(const char* str) {
return append(str, static_cast<osmium::memory::item_size_type>(std::strlen(str) + 1));
}
/// Return the buffer this builder is using.
osmium::memory::Buffer& buffer() noexcept {
return m_buffer;
}
}; // class Builder
template <class TItem>
class ObjectBuilder : public Builder {
static_assert(std::is_base_of<osmium::memory::Item, TItem>::value,
"ObjectBuilder can only build objects derived from osmium::memory::Item");
public:
explicit ObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) :
Builder(buffer, parent, sizeof(TItem)) {
new (&item()) TItem();
}
TItem& object() noexcept {
return static_cast<TItem&>(item());
}
/**
* Add user name to buffer.
*
* @param user Pointer to user name.
* @param length Length of user name including \0 byte.
*/
void add_user(const char* user, const string_size_type length) {
object().set_user_size(length);
add_size(append(user, length));
add_padding(true);
}
/**
* Add user name to buffer.
*
* @param user Pointer to \0-terminated user name.
*/
void add_user(const char* user) {
add_user(user, static_cast_with_assert<string_size_type>(std::strlen(user) + 1));
}
/**
* Add user name to buffer.
*
* @param user User name.
*/
void add_user(const std::string& user) {
add_user(user.data(), static_cast_with_assert<string_size_type>(user.size() + 1));
}
}; // class ObjectBuilder
} // namespace builder
} // namespace osmium
#endif // OSMIUM_BUILDER_BUILDER_HPP

View File

@ -46,6 +46,7 @@ DEALINGS IN THE SOFTWARE.
#include <osmium/osm/object.hpp>
#include <osmium/osm/tag.hpp>
#include <osmium/osm/types.hpp>
#include <osmium/util/cast.hpp>
namespace osmium {
@ -67,10 +68,27 @@ namespace osmium {
add_padding();
}
/**
* Add tag to buffer.
*
* @param key Tag key.
* @param value Tag value.
*/
void add_tag(const char* key, const char* value) {
add_size(append(key) + append(value));
}
/**
* Add tag to buffer.
*
* @param key Tag key.
* @param value Tag value.
*/
void add_tag(const std::string& key, const std::string& value) {
add_size(append(key.data(), static_cast_with_assert<string_size_type>(key.size() + 1)) +
append(value.data(), static_cast_with_assert<string_size_type>(value.size() + 1)));
}
}; // class TagListBuilder
template <class T>
@ -103,14 +121,42 @@ namespace osmium {
class RelationMemberListBuilder : public ObjectBuilder<RelationMemberList> {
void add_role(osmium::RelationMember* member, const char* role) {
size_t length = std::strlen(role) + 1;
assert(length < std::numeric_limits<string_size_type>::max());
member->set_role_size(static_cast<string_size_type>(length));
add_size(append(role));
/**
* Add role to buffer.
*
* @param member Relation member object where the length of the role
* will be set.
* @param role The role.
* @param length Length of role string including \0 termination.
*/
void add_role(osmium::RelationMember& member, const char* role, const string_size_type length) {
member.set_role_size(length);
add_size(append(role, length));
add_padding(true);
}
/**
* Add role to buffer.
*
* @param member Relation member object where the length of the role
* will be set.
* @param role \0-terminated role.
*/
void add_role(osmium::RelationMember& member, const char* role) {
add_role(member, role, static_cast_with_assert<string_size_type>(std::strlen(role) + 1));
}
/**
* Add role to buffer.
*
* @param member Relation member object where the length of the role
* will be set.
* @param role Role.
*/
void add_role(osmium::RelationMember& member, const std::string& role) {
add_role(member, role.data(), static_cast_with_assert<string_size_type>(role.size() + 1));
}
public:
explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent=nullptr) :
@ -121,11 +167,41 @@ namespace osmium {
add_padding();
}
/**
* Add a member to the relation.
*
* @param type The type (node, way, or relation).
* @param ref The ID of the member.
* @param role The role of the member.
* @param full_member Optional pointer to the member object. If it
* is available a copy will be added to the
* relation.
*/
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<osmium::RelationMember>();
new (member) osmium::RelationMember(ref, type, full_member != nullptr);
add_size(sizeof(RelationMember));
add_role(member, role);
add_role(*member, role);
if (full_member) {
add_item(full_member);
}
}
/**
* Add a member to the relation.
*
* @param type The type (node, way, or relation).
* @param ref The ID of the member.
* @param role The role of the member.
* @param full_member Optional pointer to the member object. If it
* is available a copy will be added to the
* relation.
*/
void add_member(osmium::item_type type, object_id_type ref, const std::string& role, const osmium::OSMObject* full_member = nullptr) {
osmium::RelationMember* member = reserve_space_for<osmium::RelationMember>();
new (member) osmium::RelationMember(ref, type, full_member != nullptr);
add_size(sizeof(RelationMember));
add_role(*member, role);
if (full_member) {
add_item(full_member);
}
@ -186,12 +262,12 @@ namespace osmium {
*/
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());
area.set_id(osmium::object_id_to_area_id(source.id(), source.type()));
area.set_version(source.version());
area.set_changeset(source.changeset());
area.set_timestamp(source.timestamp());
area.set_visible(source.visible());
area.set_uid(source.uid());
add_user(source.user());
}

View File

@ -1,195 +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 <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 <memory>
#include <utility>
#include <osmium/handler.hpp>
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 <class THandler> \
auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, int) -> decltype(handler._name_(object), void()) { \
handler._name_(object); \
} \
template <class THandler> \
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 <class THandler>
auto flush_dispatch(THandler& handler, int) -> decltype(handler.flush(), void()) {
handler.flush();
}
template <class THandler>
void flush_dispatch(THandler&, long) {}
template <class THandler>
class HandlerWrapper : public HandlerWrapperBase {
THandler m_handler;
public:
template <class... TArgs>
HandlerWrapper(TArgs&&... args) :
m_handler(std::forward<TArgs>(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<osmium::handler::detail::HandlerWrapperBase> impl_ptr;
impl_ptr m_impl;
public:
DynamicHandler() :
m_impl(impl_ptr(new osmium::handler::detail::HandlerWrapperBase)) {
}
template <class THandler, class... TArgs>
void set(TArgs&&... args) {
m_impl = impl_ptr(new osmium::handler::detail::HandlerWrapper<THandler>(std::forward<TArgs>(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
#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 <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 <memory>
#include <utility>
#include <osmium/handler.hpp>
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 <class THandler> \
auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, int) -> decltype(handler._name_(object), void()) { \
handler._name_(object); \
} \
template <class THandler> \
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 <class THandler>
auto flush_dispatch(THandler& handler, int) -> decltype(handler.flush(), void()) {
handler.flush();
}
template <class THandler>
void flush_dispatch(THandler&, long) {}
template <class THandler>
class HandlerWrapper : public HandlerWrapperBase {
THandler m_handler;
public:
template <class... TArgs>
HandlerWrapper(TArgs&&... args) :
m_handler(std::forward<TArgs>(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);
}
}; // class HandlerWrapper
} // namespace detail
class DynamicHandler : public osmium::handler::Handler {
typedef std::unique_ptr<osmium::handler::detail::HandlerWrapperBase> impl_ptr;
impl_ptr m_impl;
public:
DynamicHandler() :
m_impl(impl_ptr(new osmium::handler::detail::HandlerWrapperBase)) {
}
template <class THandler, class... TArgs>
void set(TArgs&&... args) {
m_impl = impl_ptr(new osmium::handler::detail::HandlerWrapper<THandler>(std::forward<TArgs>(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();
}
}; // class DynamicHandler
} // namspace handler
} // namespace osmium
#endif // OSMIUM_DYNAMIC_HANDLER_HPP

View File

@ -38,59 +38,50 @@ DEALINGS IN THE SOFTWARE.
#include <string>
#include <osmium/osm/location.hpp>
#include <osmium/util/double.hpp>
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) {
explicit Coordinates(double cx, double cy) noexcept : 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);
void append_to_string(std::string& s, const char infix, int precision) const {
osmium::util::double2string(s, x, precision);
s += infix;
osmium::geom::detail::double2string(s, y);
osmium::util::double2string(s, y, precision);
}
void append_to_string(std::string& s, const char prefix, const char infix, const char suffix) const {
void append_to_string(std::string& s, const char prefix, const char infix, const char suffix, int precision) const {
s += prefix;
append_to_string(s, infix);
append_to_string(s, infix, precision);
s += suffix;
}
}; // struct coordinates
inline bool operator==(const Coordinates& lhs, const Coordinates& rhs) {
/**
* Compare whether two Coordinates are identical. Might not give the
* right result if the coordinates have been the result of some
* calculation that introduced rounding errors.
*/
inline bool operator==(const Coordinates& lhs, const Coordinates& rhs) noexcept {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
return lhs.x == rhs.x && lhs.y == rhs.y;
#pragma GCC diagnostic pop
}
inline bool operator!=(const Coordinates& lhs, const Coordinates& rhs) {
inline bool operator!=(const Coordinates& lhs, const Coordinates& rhs) noexcept {
return ! operator==(lhs, rhs);
}

View File

@ -33,6 +33,7 @@ DEALINGS IN THE SOFTWARE.
*/
#include <cstddef>
#include <stdexcept>
#include <string>
#include <utility>
@ -49,6 +50,10 @@ DEALINGS IN THE SOFTWARE.
namespace osmium {
/**
* Exception thrown when an invalid geometry is encountered. An example
* would be a linestring with less than two points.
*/
struct geometry_error : public std::runtime_error {
geometry_error(const std::string& what) :
@ -72,7 +77,7 @@ namespace osmium {
enum class use_nodes : bool {
unique = true, ///< Remove consecutive nodes with same location.
all = false ///< Use all nodes.
};
}; // enum class use_nodes
/**
* Which direction the linestring created from a way
@ -81,7 +86,7 @@ namespace osmium {
enum class direction : bool {
backward = true, ///< Linestring has reverse direction.
forward = false ///< Linestring has same direction as way.
};
}; // enum class direction
/**
* This pseudo projection just returns its WGS84 input unchanged.
@ -95,7 +100,7 @@ namespace osmium {
return Coordinates{location.lon(), location.lat()};
}
int epsg() const {
int epsg() const noexcept {
return 4326;
}
@ -178,6 +183,10 @@ namespace osmium {
/* LineString */
void linestring_start() {
m_impl.linestring_start();
}
template <class TIter>
size_t fill_linestring(TIter it, TIter end) {
size_t num_points = 0;
@ -201,8 +210,12 @@ namespace osmium {
return num_points;
}
linestring_type linestring_finish(size_t num_points) {
return m_impl.linestring_finish(num_points);
}
linestring_type create_linestring(const osmium::WayNodeList& wnl, use_nodes un=use_nodes::unique, direction dir=direction::forward) {
m_impl.linestring_start();
linestring_start();
size_t num_points = 0;
if (un == use_nodes::unique) {
@ -227,16 +240,49 @@ namespace osmium {
}
if (num_points < 2) {
throw geometry_error("not enough points for linestring");
throw osmium::geometry_error("not enough points for linestring");
}
return m_impl.linestring_finish(num_points);
return 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);
}
/* Polygon */
void polygon_start() {
m_impl.polygon_start();
}
template <class TIter>
size_t fill_polygon(TIter it, TIter end) {
size_t num_points = 0;
for (; it != end; ++it, ++num_points) {
m_impl.polygon_add_location(m_projection(it->location()));
}
return num_points;
}
template <class TIter>
size_t fill_polygon_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.polygon_add_location(m_projection(last_location));
++num_points;
}
}
return num_points;
}
polygon_type polygon_finish(size_t num_points) {
return m_impl.polygon_finish(num_points);
}
/* MultiPolygon */
multipolygon_type create_multipolygon(const osmium::Area& area) {
@ -266,7 +312,7 @@ namespace osmium {
// if there are no rings, this area is invalid
if (num_rings == 0) {
throw geometry_error("invalid area");
throw osmium::geometry_error("invalid area");
}
m_impl.multipolygon_polygon_finish();

View File

@ -49,6 +49,7 @@ namespace osmium {
class GeoJSONFactoryImpl {
std::string m_str;
int m_precision;
public:
@ -58,14 +59,16 @@ namespace osmium {
typedef std::string multipolygon_type;
typedef std::string ring_type;
GeoJSONFactoryImpl() = default;
GeoJSONFactoryImpl(int precision = 7) :
m_precision(precision) {
}
/* 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, '[', ',', ']');
xy.append_to_string(str, '[', ',', ']', m_precision);
str += "}";
return str;
}
@ -78,7 +81,7 @@ namespace osmium {
}
void linestring_add_location(const osmium::geom::Coordinates& xy) {
xy.append_to_string(m_str, '[', ',', ']');
xy.append_to_string(m_str, '[', ',', ']', m_precision);
m_str += ',';
}
@ -124,7 +127,7 @@ namespace osmium {
}
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
xy.append_to_string(m_str, '[', ',', ']');
xy.append_to_string(m_str, '[', ',', ']', m_precision);
m_str += ',';
}

View File

@ -1,96 +1,94 @@
#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 <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 <cmath>
#include <iterator>
#include <osmium/geom/coordinates.hpp>
#include <osmium/geom/util.hpp>
#include <osmium/memory/collection.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/node_ref.hpp>
#include <osmium/osm/way.hpp>
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
#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 <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 <cmath>
#include <iterator>
#include <osmium/geom/coordinates.hpp>
#include <osmium/geom/util.hpp>
#include <osmium/osm/node_ref.hpp>
#include <osmium/osm/way.hpp>
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

View File

@ -46,22 +46,22 @@ namespace osmium {
namespace detail {
constexpr double EARTH_RADIUS_FOR_EPSG3857 = 6378137.0;
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);
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));
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;
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);
return rad_to_deg(2 * std::atan(std::exp(y / earth_radius_for_epsg3857)) - osmium::geom::PI/2);
}
} // namespace detail
@ -92,7 +92,7 @@ namespace osmium {
return Coordinates {detail::lon_to_x(location.lon()), detail::lat_to_y(location.lat())};
}
int epsg() const {
int epsg() const noexcept {
return 3857;
}

View File

@ -37,11 +37,16 @@ DEALINGS IN THE SOFTWARE.
#define OSMIUM_LINK_WITH_LIBS_OGR `gdal-config --libs`
#include <cassert>
#include <cstddef>
#include <memory>
#include <utility>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"
#ifdef __clang__
# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"
#endif
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wpadded"
# include <ogr_geometry.h>
#pragma GCC diagnostic pop
@ -96,6 +101,23 @@ namespace osmium {
return std::move(m_linestring);
}
/* Polygon */
void polygon_start() {
m_ring = std::unique_ptr<OGRLinearRing>(new OGRLinearRing());
}
void polygon_add_location(const osmium::geom::Coordinates& xy) {
assert(!!m_ring);
m_ring->addPoint(xy.x, xy.y);
}
polygon_type polygon_finish(size_t /* num_points */) {
std::unique_ptr<OGRPolygon> polygon = std::unique_ptr<OGRPolygon>(new OGRPolygon());
polygon->addRingDirectly(m_ring.release());
return polygon;
}
/* MultiPolygon */
void multipolygon_start() {

View File

@ -57,7 +57,7 @@ namespace osmium {
void operator()(void* crs) {
pj_free(crs);
}
};
}; // struct ProjCRSDeleter
std::unique_ptr<void, ProjCRSDeleter> m_crs;
@ -142,7 +142,7 @@ namespace osmium {
}
}
int epsg() const {
int epsg() const noexcept {
return m_epsg;
}

View File

@ -1,71 +1,75 @@
#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 <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>
#include <string>
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
#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 <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>
#include <string>
namespace osmium {
/**
* Exception thrown when a projection object can not be initialized or the
* projection of some coordinates can not be calculated.
*/
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) noexcept {
return degree * (PI / 180.0);
}
/// Convert angle from radians to degrees.
inline constexpr double rad_to_deg(double radians) noexcept {
return radians * (180.0 / PI);
}
} // namespace geom
} // namespace osmium
#endif // OSMIUM_GEOM_UTIL_HPP

View File

@ -38,8 +38,18 @@ DEALINGS IN THE SOFTWARE.
#include <cstring>
#include <string>
// Windows is only available for little endian architectures
// http://stackoverflow.com/questions/6449468/can-i-safely-assume-that-windows-installations-will-always-be-little-endian
#if !defined(_WIN32) && !defined(__APPLE__)
# include <endian.h>
#else
# define __LITTLE_ENDIAN 1234
# define __BYTE_ORDER __LITTLE_ENDIAN
#endif
#include <osmium/geom/coordinates.hpp>
#include <osmium/geom/factory.hpp>
#include <osmium/util/cast.hpp>
namespace osmium {
@ -48,12 +58,12 @@ namespace osmium {
enum class wkb_type : bool {
wkb = false,
ewkb = true
};
}; // enum class wkb_type
enum class out_type : bool {
binary = false,
hex = true
};
}; // enum class out_type
namespace detail {
@ -99,7 +109,7 @@ namespace osmium {
// SRID-presence flag (EWKB)
wkbSRID = 0x20000000
};
}; // enum wkbGeometryType
/**
* Byte order marker in WKB geometry.
@ -107,7 +117,7 @@ namespace osmium {
enum class wkb_byte_order_type : uint8_t {
XDR = 0, // Big Endian
NDR = 1 // Little Endian
};
}; // enum class wkb_byte_order_type
std::string m_data;
uint32_t m_points {0};
@ -122,7 +132,11 @@ namespace osmium {
size_t m_ring_size_offset = 0;
size_t header(std::string& str, wkbGeometryType type, bool add_length) const {
#if __BYTE_ORDER == __LITTLE_ENDIAN
str_push(str, wkb_byte_order_type::NDR);
#else
str_push(str, wkb_byte_order_type::XDR);
#endif
if (m_wkb_type == wkb_type::ewkb) {
str_push(str, type | wkbSRID);
str_push(str, srid);
@ -136,8 +150,9 @@ namespace osmium {
return offset;
}
void set_size(const size_t offset, const uint32_t size) {
memcpy(&m_data[offset], &size, sizeof(uint32_t));
void set_size(const size_t offset, const size_t size) {
const uint32_t s = static_cast_with_assert<uint32_t>(size);
memcpy(&m_data[offset], &s, sizeof(uint32_t));
}
public:

View File

@ -34,6 +34,7 @@ DEALINGS IN THE SOFTWARE.
*/
#include <cassert>
#include <cstddef>
#include <string>
#include <utility>
@ -49,6 +50,7 @@ namespace osmium {
class WKTFactoryImpl {
std::string m_str;
int m_precision;
public:
@ -58,11 +60,15 @@ namespace osmium {
typedef std::string multipolygon_type;
typedef std::string ring_type;
WKTFactoryImpl(int precision = 7) :
m_precision(precision) {
}
/* Point */
point_type make_point(const osmium::geom::Coordinates& xy) const {
std::string str {"POINT"};
xy.append_to_string(str, '(', ' ', ')');
xy.append_to_string(str, '(', ' ', ')', m_precision);
return str;
}
@ -73,7 +79,7 @@ namespace osmium {
}
void linestring_add_location(const osmium::geom::Coordinates& xy) {
xy.append_to_string(m_str, ' ');
xy.append_to_string(m_str, ' ', m_precision);
m_str += ',';
}
@ -118,7 +124,7 @@ namespace osmium {
}
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
xy.append_to_string(m_str, ' ');
xy.append_to_string(m_str, ' ', m_precision);
m_str += ',';
}

View File

@ -1,128 +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 <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 <tuple>
#include <osmium/handler.hpp>
#define OSMIUM_CHAIN_HANDLER_CALL(_func_, _type_) \
template <int N, int SIZE, class THandlers> \
struct call_ ## _func_ { \
void operator()(THandlers& handlers, osmium::_type_& object) { \
std::get<N>(handlers)._func_(object); \
call_ ## _func_<N+1, SIZE, THandlers>()(handlers, object); \
} \
}; \
template <int SIZE, class THandlers> \
struct call_ ## _func_<SIZE, SIZE, THandlers> { \
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 ...THandler>
class ChainHandler : public osmium::handler::Handler {
typedef std::tuple<THandler&...> handlers_type;
handlers_type m_handlers;
template <int N, int SIZE, class THandlers>
struct call_flush {
void operator()(THandlers& handlers) {
std::get<N>(handlers).flush();
call_flush<N+1, SIZE, THandlers>()(handlers);
}
};
template <int SIZE, class THandlers>
struct call_flush<SIZE, SIZE, THandlers> {
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
#ifndef OSMIUM_HANDLER_CHAIN_HPP
#define OSMIUM_HANDLER_CHAIN_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 <tuple>
#include <osmium/handler.hpp>
#define OSMIUM_CHAIN_HANDLER_CALL(_func_, _type_) \
template <int N, int SIZE, class THandlers> \
struct call_ ## _func_ { \
void operator()(THandlers& handlers, osmium::_type_& object) { \
std::get<N>(handlers)._func_(object); \
call_ ## _func_<N+1, SIZE, THandlers>()(handlers, object); \
} \
}; \
template <int SIZE, class THandlers> \
struct call_ ## _func_<SIZE, SIZE, THandlers> { \
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 ...THandler>
class ChainHandler : public osmium::handler::Handler {
typedef std::tuple<THandler&...> handlers_type;
handlers_type m_handlers;
template <int N, int SIZE, class THandlers>
struct call_flush {
void operator()(THandlers& handlers) {
std::get<N>(handlers).flush();
call_flush<N+1, SIZE, THandlers>()(handlers);
}
}; // struct call_flush
template <int SIZE, class THandlers>
struct call_flush<SIZE, SIZE, THandlers> {
void operator()(THandlers&) {}
}; // struct call_flush
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

View File

@ -1,294 +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 <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 <iomanip>
#include <iostream>
#include <string>
#include <osmium/handler.hpp>
#include <osmium/memory/collection.hpp>
#include <osmium/memory/item.hpp>
#include <osmium/osm/area.hpp>
#include <osmium/osm/box.hpp>
#include <osmium/osm/changeset.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/node.hpp>
#include <osmium/osm/node_ref.hpp>
#include <osmium/osm/object.hpp>
#include <osmium/osm/relation.hpp>
#include <osmium/osm/tag.hpp>
#include <osmium/osm/timestamp.hpp>
#include <osmium/osm/way.hpp>
#include <osmium/visitor.hpp>
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
#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 <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 <iomanip>
#include <iostream>
#include <string>
#include <osmium/handler.hpp>
#include <osmium/memory/collection.hpp>
#include <osmium/memory/item.hpp>
#include <osmium/osm/area.hpp>
#include <osmium/osm/box.hpp>
#include <osmium/osm/changeset.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/node.hpp>
#include <osmium/osm/node_ref.hpp>
#include <osmium/osm/object.hpp>
#include <osmium/osm/relation.hpp>
#include <osmium/osm/tag.hpp>
#include <osmium/osm/timestamp.hpp>
#include <osmium/osm/way.hpp>
#include <osmium/visitor.hpp>
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

View File

@ -1,148 +1,170 @@
#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 <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/handler.hpp>
#include <osmium/index/index.hpp>
#include <osmium/index/map/dummy.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/node.hpp>
#include <osmium/osm/node_ref.hpp>
#include <osmium/osm/types.hpp>
#include <osmium/osm/way.hpp>
namespace osmium {
namespace handler {
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> 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 TStoragePosIDs, class TStorageNegIDs = dummy_type>
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
#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 <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 <type_traits>
#include <osmium/handler.hpp>
#include <osmium/index/index.hpp>
#include <osmium/index/map/dummy.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/node.hpp>
#include <osmium/osm/node_ref.hpp>
#include <osmium/osm/types.hpp>
#include <osmium/osm/way.hpp>
namespace osmium {
namespace handler {
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> 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 TStoragePosIDs, class TStorageNegIDs = dummy_type>
class NodeLocationsForWays : public osmium::handler::Handler {
static_assert(std::is_base_of<osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>, TStoragePosIDs>::value,
"Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
static_assert(std::is_base_of<osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>, TStorageNegIDs>::value,
"Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
/// 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(static_cast<osmium::unsigned_object_id_type>( id), node.location());
} else {
m_storage_neg.set(static_cast<osmium::unsigned_object_id_type>(-id), node.location());
}
}
/**
* Get location of node with given id.
*/
osmium::Location get_node_location(const osmium::object_id_type id) const {
if (id >= 0) {
return m_storage_pos.get(static_cast<osmium::unsigned_object_id_type>( id));
} else {
return m_storage_neg.get(static_cast<osmium::unsigned_object_id_type>(-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.set_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("location for one or more nodes not found in node location index");
}
}
/**
* Call clear on the location indexes. Makes the
* NodeLocationsForWays handler unusable. Used to explicitly free
* memory if thats needed.
*/
void clear() {
m_storage_pos.clear();
m_storage_neg.clear();
}
}; // class NodeLocationsForWays
} // namespace handler
} // namespace osmium
#endif // OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP

View File

@ -1,183 +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 <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 <cstddef>
#include <new>
#include <stdexcept>
#include <osmium/index/detail/typed_mmap.hpp>
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 <typename T, template <typename> 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<T>::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<T>::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<TDerived<T>*>(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
#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 <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 <cstddef>
#include <new>
#include <stdexcept>
#include <osmium/index/detail/typed_mmap.hpp>
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 <typename T, template <typename> 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) noexcept :
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<T>::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<T>::unmap(m_data, m_capacity);
}
size_t capacity() const noexcept {
return m_capacity;
}
size_t size() const noexcept {
return m_size;
}
bool empty() const noexcept {
return m_size == 0;
}
const T* data() const noexcept {
return m_data;
}
T* data() noexcept {
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() noexcept {
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 > capacity()) {
static_cast<TDerived<T>*>(this)->reserve(new_size + osmium::detail::mmap_vector_size_increment);
}
if (new_size > size()) {
new (data() + size()) T[new_size - size()];
}
m_size = new_size;
}
iterator begin() noexcept {
return m_data;
}
iterator end() noexcept {
return m_data + m_size;
}
const_iterator begin() const noexcept {
return m_data;
}
const_iterator end() const noexcept {
return m_data + m_size;
}
const_iterator cbegin() noexcept {
return m_data;
}
const_iterator cend() noexcept {
return m_data + m_size;
}
}; // class mmap_vector_base
} // namespace detail
} // namespace osmium
#endif // OSMIUM_DETAIL_MMAP_VECTOR_BASE_HPP

View File

@ -1,83 +1,82 @@
#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 <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 <cstddef>
#include <osmium/index/detail/typed_mmap.hpp>
#include <osmium/index/detail/mmap_vector_base.hpp>
#include <osmium/index/detail/tmpfile.hpp>
namespace osmium {
namespace detail {
/**
* This class looks and behaves like STL vector, but mmap's a file internally.
*/
template <typename T>
class mmap_vector_file : public mmap_vector_base<T, mmap_vector_file> {
public:
explicit mmap_vector_file() :
mmap_vector_base<T, osmium::detail::mmap_vector_file>(
osmium::detail::create_tmp_file(),
osmium::detail::mmap_vector_size_increment,
0) {
}
explicit mmap_vector_file(int fd) :
mmap_vector_base<T, osmium::detail::mmap_vector_file>(
fd,
osmium::detail::typed_mmap<T>::file_size(fd) == 0 ? osmium::detail::mmap_vector_size_increment : osmium::detail::typed_mmap<T>::file_size(fd),
osmium::detail::typed_mmap<T>::file_size(fd)) {
}
void reserve(size_t new_capacity) {
if (new_capacity > this->capacity()) {
osmium::detail::typed_mmap<T>::unmap(this->data(), this->capacity());
osmium::detail::typed_mmap<T>::grow_file(new_capacity, this->m_fd);
osmium::detail::typed_mmap<T>::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
#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 <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 <cstddef>
#include <osmium/index/detail/typed_mmap.hpp>
#include <osmium/index/detail/mmap_vector_base.hpp>
#include <osmium/index/detail/tmpfile.hpp>
namespace osmium {
namespace detail {
/**
* This class looks and behaves like STL vector, but mmap's a file internally.
*/
template <typename T>
class mmap_vector_file : public mmap_vector_base<T, mmap_vector_file> {
public:
explicit mmap_vector_file() :
mmap_vector_base<T, osmium::detail::mmap_vector_file>(
osmium::detail::create_tmp_file(),
osmium::detail::mmap_vector_size_increment,
0) {
}
explicit mmap_vector_file(int fd) :
mmap_vector_base<T, osmium::detail::mmap_vector_file>(
fd,
osmium::detail::typed_mmap<T>::file_size(fd) == 0 ? osmium::detail::mmap_vector_size_increment : osmium::detail::typed_mmap<T>::file_size(fd),
osmium::detail::typed_mmap<T>::file_size(fd)) {
}
void reserve(size_t new_capacity) {
if (new_capacity > this->capacity()) {
osmium::detail::typed_mmap<T>::unmap(this->data(), this->capacity());
this->data(osmium::detail::typed_mmap<T>::grow_and_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

View File

@ -44,8 +44,8 @@ namespace osmium {
/**
* 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.
* @returns File descriptor of temporary file.
* @throws std::system_error if something went wrong.
*/
inline int create_tmp_file() {
FILE* file = ::tmpfile();

View File

@ -38,18 +38,18 @@ DEALINGS IN THE SOFTWARE.
#include <stdexcept>
#include <system_error>
#ifndef WIN32
#include <sys/stat.h>
#ifndef _WIN32
# include <sys/mman.h>
#else
# include <mmap_for_windows.hpp>
#endif
#include <sys/stat.h>
#ifdef _MSC_VER
# define ftruncate _chsize
#else
#ifndef _MSC_VER
# include <unistd.h>
#else
# define ftruncate _chsize
#endif
// for bsd systems
@ -57,6 +57,8 @@ DEALINGS IN THE SOFTWARE.
# define MAP_ANONYMOUS MAP_ANON
#endif
#include <osmium/util/cast.hpp>
namespace osmium {
/**
@ -89,8 +91,8 @@ namespace osmium {
* 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
* @returns Pointer to mapped memory
* @throws 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);
@ -113,8 +115,8 @@ namespace osmium {
* @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
* @returns Pointer to mapped memory
* @throws std::system_error If mmap(2) failed
*/
static T* map(size_t size, int fd, bool write = false) {
int prot = PROT_READ;
@ -141,7 +143,7 @@ namespace osmium {
* @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
* @throws 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<void*>(data), sizeof(T) * old_size, sizeof(T) * new_size, MREMAP_MAYMOVE);
@ -162,7 +164,7 @@ namespace osmium {
*
* @param data Pointer to the data
* @param size Number of objects of type T stored
* @exception std::system_error If munmap(2) call failed
* @throws std::system_error If munmap(2) call failed
*/
static void unmap(T* data, size_t size) {
if (::munmap(reinterpret_cast<void*>(data), sizeof(T) * size) != 0) {
@ -174,19 +176,19 @@ namespace osmium {
* 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)
* @returns Number of objects of type T in this file
* @throws std::system_error If fstat(2) call failed
* @throws 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) {
if (static_cast<size_t>(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);
return static_cast<size_t>(s.st_size) / sizeof(T);
}
/**
@ -196,11 +198,11 @@ namespace osmium {
*
* @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
* @throws 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) {
if (::ftruncate(fd, static_cast_with_assert<off_t>(sizeof(T) * new_size)) < 0) {
throw std::system_error(errno, std::system_category(), "ftruncate failed");
}
}
@ -211,7 +213,7 @@ namespace osmium {
*
* @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()
* @throws Errors thrown by grow_file() or map()
*/
static T* grow_and_map(size_t size, int fd) {
grow_file(size, fd);

View File

@ -1,156 +1,155 @@
#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 <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 <cstddef>
#include <type_traits>
#include <osmium/index/index.hpp> // 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 <typename TId, typename TValue>
class Map {
static_assert(std::is_integral<TId>::value && std::is_unsigned<TId>::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
#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 <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 <cstddef>
#include <type_traits>
#include <osmium/index/index.hpp> // 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 <typename TId, typename TValue>
class Map {
static_assert(std::is_integral<TId>::value && std::is_unsigned<TId>::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;
virtual ~Map() = default;
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
}
virtual void dump_as_list(int /*fd*/) const {
std::runtime_error("can't dump as list");
}
}; // class Map
} // namespace map
} // namespace index
} // namespace osmium
#endif // OSMIUM_INDEX_MAP_HPP

View File

@ -1,140 +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 <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 <cstddef>
#include <stdexcept>
#include <utility>
#include <vector>
#include <google/sparsetable>
#include <osmium/index/map.hpp>
#include <osmium/io/detail/read_write.hpp>
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 <typename TId, typename TValue>
class SparseTable : public osmium::index::map::Map<TId, TValue> {
TId m_grow_size;
google::sparsetable<TValue> m_elements;
static_assert(sizeof(typename google::sparsetable<TValue>::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<TValue>()) {
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<std::pair<TId, TValue>> v;
int n=0;
for (const TValue value : m_elements) {
if (value != osmium::index::empty_value<TValue>()) {
v.emplace_back(n, value);
}
++n;
}
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(v.data()), sizeof(std::pair<TId, TValue>) * v.size());
}
}; // class SparseTable
} // namespace map
} // namespace index
} // namespace osmium
#endif // OSMIUM_INDEX_BYID_SPARSE_TABLE_HPP
#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 <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 <cstddef>
#include <stdexcept>
#include <utility>
#include <vector>
#include <google/sparsetable>
#include <osmium/index/map.hpp>
#include <osmium/io/detail/read_write.hpp>
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 <typename TId, typename TValue>
class SparseTable : public osmium::index::map::Map<TId, TValue> {
TId m_grow_size;
google::sparsetable<TValue> m_elements;
static_assert(sizeof(typename google::sparsetable<TValue>::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<TValue>()) {
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 override final {
std::vector<std::pair<TId, TValue>> v;
int n=0;
for (const TValue value : m_elements) {
if (value != osmium::index::empty_value<TValue>()) {
v.emplace_back(n, value);
}
++n;
}
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(v.data()), sizeof(std::pair<TId, TValue>) * v.size());
}
}; // class SparseTable
} // namespace map
} // namespace index
} // namespace osmium
#endif // OSMIUM_INDEX_BYID_SPARSE_TABLE_HPP

View File

@ -1,112 +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 <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 <algorithm>
#include <cstddef>
#include <iterator>
#include <map>
#include <stdexcept>
#include <vector>
#include <osmium/index/map.hpp>
#include <osmium/io/detail/read_write.hpp>
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 <typename TId, typename TValue>
class StlMap : public osmium::index::map::Map<TId, TValue> {
// 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<TId, TValue> 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<TId, TValue>::value_type t;
std::vector<t> v;
std::copy(m_elements.begin(), m_elements.end(), std::back_inserter(v));
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(v.data()), sizeof(t) * v.size());
}
}; // class StlMap
} // namespace map
} // namespace index
} // namespace osmium
#endif // OSMIUM_INDEX_MAP_STL_MAP_HPP
#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 <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 <algorithm>
#include <cstddef>
#include <iterator>
#include <map>
#include <stdexcept>
#include <vector>
#include <osmium/index/map.hpp>
#include <osmium/io/detail/read_write.hpp>
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 <typename TId, typename TValue>
class StlMap : public osmium::index::map::Map<TId, TValue> {
// 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<TId, TValue> 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 override final {
typedef typename std::map<TId, TValue>::value_type t;
std::vector<t> v;
std::copy(m_elements.begin(), m_elements.end(), std::back_inserter(v));
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(v.data()), sizeof(t) * v.size());
}
}; // class StlMap
} // namespace map
} // namespace index
} // namespace osmium
#endif // OSMIUM_INDEX_MAP_STL_MAP_HPP

View File

@ -1,208 +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 <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 <algorithm>
#include <cstddef>
#include <stdexcept>
#include <utility>
#include <osmium/index/map.hpp>
#include <osmium/io/detail/read_write.hpp>
namespace osmium {
namespace index {
namespace map {
template <class TVector, typename TId, typename TValue>
class VectorBasedDenseMap : public Map<TId, TValue> {
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<TValue>()) {
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 <typename TId, typename TValue, template<typename...> class TVector>
class VectorBasedSparseMap : public Map<TId, TValue> {
public:
typedef typename std::pair<TId, TValue> element_type;
typedef TVector<element_type> 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<TValue>()
};
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<const char*>(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
#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 <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 <algorithm>
#include <cstddef>
#include <stdexcept>
#include <utility>
#include <osmium/index/map.hpp>
#include <osmium/io/detail/read_write.hpp>
namespace osmium {
namespace index {
namespace map {
template <class TVector, typename TId, typename TValue>
class VectorBasedDenseMap : public Map<TId, TValue> {
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<TValue>()) {
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 <typename TId, typename TValue, template<typename...> class TVector>
class VectorBasedSparseMap : public Map<TId, TValue> {
public:
typedef typename std::pair<TId, TValue> element_type;
typedef TVector<element_type> 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<TValue>()
};
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 override final {
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(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

View File

@ -1,125 +1,129 @@
#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 <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 <cstddef>
#include <type_traits>
#include <utility>
#include <osmium/index/index.hpp> // IWYU pragma: export
namespace osmium {
namespace index {
/**
* @brief Key-value containers with multiple values for an integer key
*/
namespace multimap {
template <typename TId, typename TValue>
class Multimap {
static_assert(std::is_integral<TId>::value && std::is_unsigned<TId>::value,
"TId template parameter for class Multimap must be unsigned integral type");
typedef typename std::pair<TId, TValue> 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<iterator, iterator> 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
#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 <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 <cstddef>
#include <type_traits>
#include <utility>
#include <osmium/index/index.hpp> // IWYU pragma: export
namespace osmium {
namespace index {
/**
* @brief Key-value containers with multiple values for an integer key
*/
namespace multimap {
template <typename TId, typename TValue>
class Multimap {
static_assert(std::is_integral<TId>::value && std::is_unsigned<TId>::value,
"TId template parameter for class Multimap must be unsigned integral type");
typedef typename std::pair<TId, TValue> 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<iterator, iterator> 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
}
virtual void dump_as_list(int /*fd*/) const {
std::runtime_error("can't dump as list");
}
}; // class Multimap
} // namespace map
} // namespace index
} // namespace osmium
#endif // OSMIUM_INDEX_MULTIMAP_HPP

View File

@ -1,199 +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 <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 <cstddef>
#include <utility>
#include <osmium/index/multimap.hpp>
#include <osmium/index/multimap/stl_vector.hpp>
#include <osmium/index/multimap/stl_multimap.hpp>
namespace osmium {
namespace index {
namespace multimap {
template <typename TId, typename TValue>
class HybridIterator {
typedef SparseMultimapMem<TId, TValue> main_map_type;
typedef StlMultimap<TId, TValue> extra_map_type;
typedef typename std::pair<TId, TValue> 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<TValue>()) { // ignore removed elements
++m_begin_main;
}
}
return *this;
}
HybridIterator<TId, TValue> 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 <typename TId, typename TValue>
class Hybrid : public Multimap<TId, TValue> {
typedef SparseMultimapMem<TId, TValue> main_map_type;
typedef StlMultimap<TId, TValue> extra_map_type;
main_map_type m_main;
extra_map_type m_extra;
public:
typedef HybridIterator<TId, TValue> iterator;
typedef const HybridIterator<TId, TValue> 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<iterator, iterator> 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
#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 <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 <cstddef>
#include <utility>
#include <osmium/index/multimap.hpp>
#include <osmium/index/multimap/stl_vector.hpp>
#include <osmium/index/multimap/stl_multimap.hpp>
namespace osmium {
namespace index {
namespace multimap {
template <typename TId, typename TValue>
class HybridIterator {
typedef SparseMultimapMem<TId, TValue> main_map_type;
typedef StlMultimap<TId, TValue> extra_map_type;
typedef typename std::pair<TId, TValue> 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<TValue>()) { // ignore removed elements
++m_begin_main;
}
}
return *this;
}
HybridIterator<TId, TValue> 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*();
}
}; // class HybridIterator
template <typename TId, typename TValue>
class Hybrid : public Multimap<TId, TValue> {
typedef SparseMultimapMem<TId, TValue> main_map_type;
typedef StlMultimap<TId, TValue> extra_map_type;
main_map_type m_main;
extra_map_type m_extra;
public:
typedef HybridIterator<TId, TValue> iterator;
typedef const HybridIterator<TId, TValue> 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<iterator, iterator> 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) override final {
consolidate();
m_main.dump_as_list(fd);
}
void clear() override final {
m_main.clear();
m_extra.clear();
}
void sort() override final {
m_main.sort();
}
}; // class Hybrid
} // namespace multimap
} // namespace index
} // namespace osmium
#endif // OSMIUM_INDEX_MULTIMAP_HYBRID_HPP

View File

@ -1,151 +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 <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 <algorithm>
#include <cstddef>
#include <map>
#include <utility>
#include <vector>
#include <osmium/index/multimap.hpp>
#include <osmium/io/detail/read_write.hpp>
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 <typename TId, typename TValue>
class StlMultimap : public osmium::index::multimap::Multimap<TId, TValue> {
// 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<const TId, TValue> 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<TId, TValue> 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<iterator, iterator> get_all(const TId id) {
return m_elements.equal_range(id);
}
std::pair<const_iterator, const_iterator> get_all(const TId id) const {
return m_elements.equal_range(id);
}
void remove(const TId id, const TValue value) {
std::pair<iterator, iterator> 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<element_type> 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<const char*>(v.data()), sizeof(element_type) * v.size());
}
}; // class StlMultimap
} // namespace multimap
} // namespace index
} // namespace osmium
#endif // OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP
#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 <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 <algorithm>
#include <cstddef>
#include <map>
#include <utility>
#include <vector>
#include <osmium/index/multimap.hpp>
#include <osmium/io/detail/read_write.hpp>
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 <typename TId, typename TValue>
class StlMultimap : public osmium::index::multimap::Multimap<TId, TValue> {
// 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<const TId, TValue> 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<TId, TValue> 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<iterator, iterator> get_all(const TId id) {
return m_elements.equal_range(id);
}
std::pair<const_iterator, const_iterator> get_all(const TId id) const {
return m_elements.equal_range(id);
}
void remove(const TId id, const TValue value) {
std::pair<iterator, iterator> 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 override final {
std::vector<element_type> 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<const char*>(v.data()), sizeof(element_type) * v.size());
}
}; // class StlMultimap
} // namespace multimap
} // namespace index
} // namespace osmium
#endif // OSMIUM_INDEX_MULTIMAP_STL_MULTIMAP_HPP

View File

@ -1,141 +1,151 @@
#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 <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 <algorithm>
#include <cstddef>
#include <utility>
#include <osmium/index/multimap.hpp>
#include <osmium/io/detail/read_write.hpp>
namespace osmium {
namespace index {
namespace multimap {
template <typename TId, typename TValue, template<typename...> class TVector>
class VectorBasedSparseMultimap : public Multimap<TId, TValue> {
public:
typedef typename std::pair<TId, TValue> element_type;
typedef TVector<element_type> 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<TValue>();
}
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<iterator, iterator> get_all(const TId id) {
const element_type element {
id,
osmium::index::empty_value<TValue>()
};
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<const char*>(m_vector.data()), byte_size());
}
}; // class VectorBasedSparseMultimap
} // namespace multimap
} // namespace index
} // namespace osmium
#endif // OSMIUM_INDEX_MULTIMAP_VECTOR_HPP
#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 <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 <algorithm>
#include <cstddef>
#include <utility>
#include <osmium/index/multimap.hpp>
#include <osmium/io/detail/read_write.hpp>
namespace osmium {
namespace index {
namespace multimap {
template <typename TId, typename TValue, template<typename...> class TVector>
class VectorBasedSparseMultimap : public Multimap<TId, TValue> {
public:
typedef typename std::pair<TId, TValue> element_type;
typedef TVector<element_type> 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<TValue>();
}
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<iterator, iterator> get_all(const TId id) {
const element_type element {
id,
osmium::index::empty_value<TValue>()
};
return std::equal_range(m_vector.begin(), m_vector.end(), element, [](const element_type& a, const element_type& b) {
return a.first < b.first;
});
}
std::pair<const_iterator, const_iterator> get_all(const TId id) const {
const element_type element {
id,
osmium::index::empty_value<TValue>()
};
return std::equal_range(m_vector.cbegin(), m_vector.cend(), 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 override final {
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size());
}
}; // class VectorBasedSparseMultimap
} // namespace multimap
} // namespace index
} // namespace osmium
#endif // OSMIUM_INDEX_MULTIMAP_VECTOR_HPP

View File

@ -40,22 +40,50 @@ DEALINGS IN THE SOFTWARE.
#include <string>
#include <bzlib.h>
#ifndef _MSC_VER
# include <unistd.h>
#endif
#include <osmium/io/compression.hpp>
#include <osmium/io/file_compression.hpp>
#include <osmium/util/cast.hpp>
#include <osmium/util/compatibility.hpp>
namespace osmium {
/**
* Exception thrown when there are problems compressing or
* decompressing bzip2 files.
*/
struct bzip2_error : public std::runtime_error {
int bzip2_error_code;
int system_errno;
bzip2_error(const std::string& what, int error_code) :
std::runtime_error(what),
bzip2_error_code(error_code),
system_errno(error_code == BZ_IO_ERROR ? errno : 0) {
}
}; // struct bzip2_error
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));
OSMIUM_NORETURN inline void throw_bzip2_error(BZFILE* bzfile, const char* msg, int bzlib_error=0) {
std::string error("bzip2 error: ");
error += msg;
error += ": ";
int errnum = bzlib_error;
if (bzlib_error) {
error += std::to_string(bzlib_error);
} else {
error += ::BZ2_bzerror(bzfile, &errnum);
}
throw osmium::bzip2_error(error, errnum);
}
} // namespace detail
@ -74,19 +102,19 @@ namespace osmium {
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);
detail::throw_bzip2_error(m_bzfile, "write open failed", m_bzerror);
}
}
~Bzip2Compressor() override final {
this->close();
close();
}
void write(const std::string& data) override final {
int error;
::BZ2_bzWrite(&error, m_bzfile, const_cast<char*>(data.data()), data.size());
::BZ2_bzWrite(&error, m_bzfile, const_cast<char*>(data.data()), static_cast_with_assert<int>(data.size()));
if (error != BZ_OK && error != BZ_STREAM_END) {
detail::throw_bzip2_error("write failed", error);
detail::throw_bzip2_error(m_bzfile, "write failed", error);
}
}
@ -99,7 +127,7 @@ namespace osmium {
fclose(m_file);
}
if (error != BZ_OK) {
detail::throw_bzip2_error("write close failed", error);
detail::throw_bzip2_error(m_bzfile, "write close failed", error);
}
}
}
@ -121,12 +149,12 @@ namespace osmium {
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);
detail::throw_bzip2_error(m_bzfile, "read open failed", m_bzerror);
}
}
~Bzip2Decompressor() override final {
this->close();
close();
}
std::string read() override final {
@ -135,9 +163,9 @@ namespace osmium {
}
std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0');
int error;
int nread = ::BZ2_bzRead(&error, m_bzfile, const_cast<char*>(buffer.data()), buffer.size());
int nread = ::BZ2_bzRead(&error, m_bzfile, const_cast<char*>(buffer.data()), static_cast_with_assert<int>(buffer.size()));
if (error != BZ_OK && error != BZ_STREAM_END) {
detail::throw_bzip2_error("read failed", error);
detail::throw_bzip2_error(m_bzfile, "read failed", error);
}
if (error == BZ_STREAM_END) {
void* unused;
@ -145,16 +173,16 @@ namespace osmium {
if (! feof(m_file)) {
::BZ2_bzReadGetUnused(&error, m_bzfile, &unused, &nunused);
if (error != BZ_OK) {
detail::throw_bzip2_error("get unused failed", error);
detail::throw_bzip2_error(m_bzfile, "get unused failed", error);
}
std::string unused_data(static_cast<const char*>(unused), static_cast<std::string::size_type>(nunused));
::BZ2_bzReadClose(&error, m_bzfile);
if (error != BZ_OK) {
detail::throw_bzip2_error("read close failed", error);
detail::throw_bzip2_error(m_bzfile, "read close failed", error);
}
m_bzfile = ::BZ2_bzReadOpen(&error, m_file, 0, 0, const_cast<void*>(static_cast<const void*>(unused_data.data())), unused_data.size());
m_bzfile = ::BZ2_bzReadOpen(&error, m_file, 0, 0, const_cast<void*>(static_cast<const void*>(unused_data.data())), static_cast_with_assert<int>(unused_data.size()));
if (error != BZ_OK) {
detail::throw_bzip2_error("read open failed", error);
detail::throw_bzip2_error(m_bzfile, "read open failed", error);
}
} else {
m_stream_end = true;
@ -173,18 +201,71 @@ namespace osmium {
fclose(m_file);
}
if (error != BZ_OK) {
detail::throw_bzip2_error("read close failed", error);
detail::throw_bzip2_error(m_bzfile, "read close failed", error);
}
}
}
}; // class Bzip2Decompressor
class Bzip2BufferDecompressor : public Decompressor {
const char* m_buffer;
size_t m_buffer_size;
bz_stream m_bzstream;
public:
Bzip2BufferDecompressor(const char* buffer, size_t size) :
m_buffer(buffer),
m_buffer_size(size),
m_bzstream() {
m_bzstream.next_in = const_cast<char*>(buffer);
m_bzstream.avail_in = static_cast_with_assert<unsigned int>(size);
int result = BZ2_bzDecompressInit(&m_bzstream, 0, 0);
if (result != BZ_OK) {
std::string message("bzip2 error: decompression init failed: ");
throw bzip2_error(message, result);
}
}
~Bzip2BufferDecompressor() override final {
BZ2_bzDecompressEnd(&m_bzstream);
}
std::string read() override final {
if (!m_buffer) {
return std::string();
}
const size_t buffer_size = 10240;
std::string output(buffer_size, '\0');
m_bzstream.next_out = const_cast<char*>(output.data());
m_bzstream.avail_out = buffer_size;
int result = BZ2_bzDecompress(&m_bzstream);
if (result != BZ_OK) {
m_buffer = nullptr;
m_buffer_size = 0;
}
if (result != BZ_OK && result != BZ_STREAM_END) {
std::string message("bzip2 error: decompress failed: ");
throw bzip2_error(message, result);
}
output.resize(static_cast<unsigned long>(m_bzstream.next_out - output.data()));
return output;
}
}; // class Bzip2BufferDecompressor
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); }
[](int fd) { return new osmium::io::Bzip2Decompressor(fd); },
[](const char* buffer, size_t size) { return new osmium::io::Bzip2BufferDecompressor(buffer, size); }
);
} // anonymous namespace

View File

@ -40,13 +40,14 @@ DEALINGS IN THE SOFTWARE.
#include <stdexcept>
#include <string>
#include <system_error>
#ifndef _MSC_VER
#include <unistd.h>
#else
#include <io.h>
#endif
#include <utility>
#ifndef _MSC_VER
# include <unistd.h>
#else
# include <io.h>
#endif
#include <osmium/io/detail/read_write.hpp>
#include <osmium/io/file_compression.hpp>
#include <osmium/util/compatibility.hpp>
@ -89,7 +90,8 @@ namespace osmium {
virtual std::string read() = 0;
virtual void close() = 0;
virtual void close() {
}
}; // class Decompressor
@ -105,11 +107,12 @@ namespace osmium {
public:
typedef std::function<osmium::io::Compressor*(int)> create_compressor_type;
typedef std::function<osmium::io::Decompressor*(int)> create_decompressor_type;
typedef std::function<osmium::io::Decompressor*(int)> create_decompressor_type_fd;
typedef std::function<osmium::io::Decompressor*(const char*, size_t)> create_decompressor_type_buffer;
private:
typedef std::map<const osmium::io::file_compression, std::pair<create_compressor_type, create_decompressor_type>> compression_map_type;
typedef std::map<const osmium::io::file_compression, std::tuple<create_compressor_type, create_decompressor_type_fd, create_decompressor_type_buffer>> compression_map_type;
compression_map_type m_callbacks;
@ -135,8 +138,13 @@ namespace osmium {
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));
bool register_compression(
osmium::io::file_compression compression,
create_compressor_type create_compressor,
create_decompressor_type_fd create_decompressor_fd,
create_decompressor_type_buffer create_decompressor_buffer) {
compression_map_type::value_type cc(compression, std::make_tuple(create_compressor, create_decompressor_fd, create_decompressor_buffer));
return m_callbacks.insert(cc).second;
}
@ -144,7 +152,7 @@ namespace osmium {
auto it = m_callbacks.find(compression);
if (it != m_callbacks.end()) {
return std::unique_ptr<osmium::io::Compressor>((it->second.first)(fd));
return std::unique_ptr<osmium::io::Compressor>(std::get<0>(it->second)(fd));
}
error(compression);
@ -154,7 +162,17 @@ namespace osmium {
auto it = m_callbacks.find(compression);
if (it != m_callbacks.end()) {
return std::unique_ptr<osmium::io::Decompressor>((it->second.second)(fd));
return std::unique_ptr<osmium::io::Decompressor>(std::get<1>(it->second)(fd));
}
error(compression);
}
std::unique_ptr<osmium::io::Decompressor> create_decompressor(osmium::io::file_compression compression, const char* buffer, size_t size) {
auto it = m_callbacks.find(compression);
if (it != m_callbacks.end()) {
return std::unique_ptr<osmium::io::Decompressor>(std::get<2>(it->second)(buffer, size));
}
error(compression);
@ -174,7 +192,7 @@ namespace osmium {
}
~NoCompressor() override final {
this->close();
close();
}
void write(const std::string& data) override final {
@ -193,26 +211,46 @@ namespace osmium {
class NoDecompressor : public Decompressor {
int m_fd;
const char *m_buffer;
size_t m_buffer_size;
public:
NoDecompressor(int fd) :
Decompressor(),
m_fd(fd) {
m_fd(fd),
m_buffer(nullptr),
m_buffer_size(0) {
}
NoDecompressor(const char* buffer, size_t size) :
Decompressor(),
m_fd(-1),
m_buffer(buffer),
m_buffer_size(size) {
}
~NoDecompressor() override final {
this->close();
close();
}
std::string read() override final {
std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0');
ssize_t nread = ::read(m_fd, const_cast<char*>(buffer.data()), buffer.size());
if (nread < 0) {
throw std::system_error(errno, std::system_category(), "Read failed");
if (m_buffer) {
if (m_buffer_size == 0) {
return std::string();
}
size_t size = m_buffer_size;
m_buffer_size = 0;
return std::string(m_buffer, size);
} else {
std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0');
ssize_t nread = ::read(m_fd, const_cast<char*>(buffer.data()), buffer.size());
if (nread < 0) {
throw std::system_error(errno, std::system_category(), "Read failed");
}
buffer.resize(static_cast<size_t>(nread));
return buffer;
}
buffer.resize(static_cast<size_t>(nread));
return buffer;
}
void close() override final {
@ -228,7 +266,8 @@ namespace osmium {
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); }
[](int fd) { return new osmium::io::NoDecompressor(fd); },
[](const char* buffer, size_t size) { return new osmium::io::NoDecompressor(buffer, size); }
);
} // anonymous namespace

View File

@ -76,7 +76,7 @@ namespace osmium {
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());
m_header.set_has_multiple_object_versions(m_file.has_multiple_object_versions());
}
InputFormat(const InputFormat&) = delete;

View File

@ -48,12 +48,22 @@ DEALINGS IN THE SOFTWARE.
#include <boost/version.hpp>
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wmissing-noreturn"
# pragma clang diagnostic ignored "-Wsign-conversion"
#endif
#if BOOST_VERSION >= 104800
# include <boost/regex/pending/unicode_iterator.hpp>
#else
# include <boost_unicode_iterator.hpp>
#endif
#ifdef __clang__
# pragma clang diagnostic pop
#endif
#include <osmium/handler.hpp>
#include <osmium/io/detail/output_format.hpp>
#include <osmium/io/file_format.hpp>
@ -95,10 +105,13 @@ namespace osmium {
template <typename... TArgs>
void output_formatted(const char* format, TArgs&&... args) {
#ifndef NDEBUG
int len =
#endif
#ifndef _MSC_VER
int len = snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward<TArgs>(args)...);
snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward<TArgs>(args)...);
#else
int len = _snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward<TArgs>(args)...);
_snprintf(m_tmp_buffer, tmp_buffer_size, format, std::forward<TArgs>(args)...);
#endif
assert(len > 0 && static_cast<size_t>(len) < tmp_buffer_size);
m_out += m_tmp_buffer;
@ -269,7 +282,7 @@ namespace osmium {
}
void write_buffer(osmium::memory::Buffer&& buffer) override final {
OPLOutputBlock output_block(std::move(buffer));
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
@ -287,10 +300,13 @@ namespace osmium {
namespace {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
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);
});
#pragma GCC diagnostic pop
} // anonymous namespace

View File

@ -40,7 +40,7 @@ DEALINGS IN THE SOFTWARE.
#include <osmpbf/osmpbf.h>
// needed for htonl and ntohl
#ifndef WIN32
#ifndef _WIN32
# include <netinet/in.h>
#else
# include <winsock2.h>
@ -50,6 +50,9 @@ DEALINGS IN THE SOFTWARE.
namespace osmium {
// avoid g++ false positive
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type"
inline item_type osmpbf_membertype_to_item_type(const OSMPBF::Relation::MemberType mt) {
switch (mt) {
case OSMPBF::Relation::NODE:
@ -60,6 +63,7 @@ namespace osmium {
return item_type::relation;
}
}
#pragma GCC diagnostic pop
inline OSMPBF::Relation::MemberType item_type_to_osmpbf_membertype(const item_type type) {
switch (type) {

View File

@ -33,7 +33,6 @@ DEALINGS IN THE SOFTWARE.
*/
#include <algorithm>
#include <atomic>
#include <cassert>
@ -53,6 +52,7 @@ DEALINGS IN THE SOFTWARE.
#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/file.hpp>
#include <osmium/io/file_format.hpp>
#include <osmium/io/header.hpp>
#include <osmium/memory/buffer.hpp>
@ -65,9 +65,26 @@ DEALINGS IN THE SOFTWARE.
#include <osmium/thread/name.hpp>
#include <osmium/thread/pool.hpp>
#include <osmium/thread/queue.hpp>
#include <osmium/util/cast.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;
@ -76,10 +93,10 @@ namespace osmium {
class PBFPrimitiveBlockParser {
static constexpr size_t initial_buffer_size = 10 * 1024;
static constexpr size_t initial_buffer_size = 2 * 1024 * 1024;
const void* m_data;
const size_t m_size;
const int m_size;
const OSMPBF::StringTable* m_stringtable;
int64_t m_lon_offset;
@ -99,7 +116,7 @@ namespace osmium {
public:
explicit PBFPrimitiveBlockParser(const void* data, const size_t size, osmium::osm_entity_bits::type read_types) :
explicit PBFPrimitiveBlockParser(const void* data, const int size, osmium::osm_entity_bits::type read_types) :
m_data(data),
m_size(size),
m_stringtable(nullptr),
@ -116,7 +133,7 @@ namespace osmium {
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.");
throw osmium::pbf_error("failed to parse PrimitiveBlock");
}
m_stringtable = &pbf_primitive_block.stringtable();
@ -137,7 +154,7 @@ namespace osmium {
} 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.");
throw osmium::pbf_error("group of unknown type");
}
}
@ -150,19 +167,19 @@ namespace osmium {
void parse_attributes(TBuilder& builder, const TPBFObject& pbf_object) {
auto& object = builder.object();
object.id(pbf_object.id());
object.set_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());
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.visible(pbf_object.info().visible());
object.set_visible(pbf_object.info().visible());
}
builder.add_user(m_stringtable->s(pbf_object.info().user_sid()).data());
builder.add_user(m_stringtable->s(static_cast_with_assert<int>(pbf_object.info().user_sid())));
} else {
builder.add_user("");
builder.add_user("", 1);
}
}
@ -173,7 +190,7 @@ namespace osmium {
parse_attributes(builder, pbf_node);
if (builder.object().visible()) {
builder.object().location(osmium::Location(
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)));
}
@ -181,8 +198,8 @@ namespace osmium {
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))).data(),
m_stringtable->s(static_cast<int>(pbf_node.vals(tag))).data());
tl_builder.add_tag(m_stringtable->s(static_cast<int>(pbf_node.keys(tag))),
m_stringtable->s(static_cast<int>(pbf_node.vals(tag))));
}
}
@ -208,8 +225,8 @@ namespace osmium {
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))).data(),
m_stringtable->s(static_cast<int>(pbf_way.vals(tag))).data());
tl_builder.add_tag(m_stringtable->s(static_cast<int>(pbf_way.keys(tag))),
m_stringtable->s(static_cast<int>(pbf_way.vals(tag))));
}
}
@ -228,15 +245,15 @@ namespace osmium {
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());
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))).data(),
m_stringtable->s(static_cast<int>(pbf_relation.vals(tag))).data());
tl_builder.add_tag(m_stringtable->s(static_cast<int>(pbf_relation.keys(tag))),
m_stringtable->s(static_cast<int>(pbf_relation.vals(tag))));
}
}
@ -262,8 +279,8 @@ namespace osmium {
break;
}
tl_builder.add_tag(m_stringtable->s(tag_key_pos).data(),
m_stringtable->s(dense.keys_vals(n)).data());
tl_builder.add_tag(m_stringtable->s(tag_key_pos),
m_stringtable->s(dense.keys_vals(n)));
++n;
}
@ -307,23 +324,23 @@ namespace osmium {
osmium::builder::NodeBuilder builder(m_buffer);
osmium::Node& node = builder.object();
node.id(last_dense_id);
node.set_id(last_dense_id);
if (dense.has_denseinfo()) {
auto v = dense.denseinfo().version(i);
assert(v > 0);
node.version(static_cast<osmium::object_version_type>(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());
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("");
builder.add_user("", 1);
}
if (visible) {
builder.object().location(osmium::Location(
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)));
}
@ -362,7 +379,7 @@ namespace osmium {
return true;
}
};
}; // class InputQueueReader
template <class TDerived>
class BlobParser {
@ -380,13 +397,10 @@ namespace osmium {
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());
throw osmium::pbf_error(std::string("invalid blob size: " + std::to_string(size)));
}
if (! input_queue_reader(m_input_buffer.get(), size)) {
// EOF
throw std::runtime_error("read error (EOF)");
if (! input_queue_reader(m_input_buffer.get(), static_cast<size_t>(size))) {
throw osmium::pbf_error("truncated data (EOF encountered)");
}
}
@ -395,7 +409,7 @@ namespace osmium {
void doit() {
OSMPBF::Blob pbf_blob;
if (!pbf_blob.ParseFromArray(m_input_buffer.get(), m_size)) {
throw std::runtime_error("failed to parse blob");
throw osmium::pbf_error("failed to parse blob");
}
if (pbf_blob.has_raw()) {
@ -410,16 +424,16 @@ namespace osmium {
static_cast<TDerived*>(this)->handle_blob(unpack_buffer);
return;
} else if (pbf_blob.has_lzma_data()) {
throw std::runtime_error("lzma blobs not implemented");
throw osmium::pbf_error("lzma blobs not implemented");
} else {
throw std::runtime_error("Blob contains no data");
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 std::runtime_error("failed to parse blob");
throw osmium::pbf_error("failed to parse blob");
}
if (pbf_blob.has_raw()) {
@ -432,9 +446,9 @@ namespace osmium {
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 std::runtime_error("lzma blobs not implemented");
throw osmium::pbf_error("lzma blobs not implemented");
} else {
throw std::runtime_error("Blob contains no data");
throw osmium::pbf_error("blob contains no data");
}
}
@ -446,8 +460,8 @@ namespace osmium {
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.");
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) {
@ -459,13 +473,16 @@ namespace osmium {
continue;
}
if (feature == "HistoricalInformation") {
m_header.has_multiple_object_versions(true);
m_header.set_has_multiple_object_versions(true);
continue;
}
std::ostringstream errmsg;
errmsg << "Required feature not supported: " << feature;
throw std::runtime_error(errmsg.str());
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()) {
@ -510,7 +527,7 @@ namespace osmium {
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);
PBFPrimitiveBlockParser parser(data.data(), static_cast_with_assert<int>(data.size()), m_read_types);
return std::move(parser());
}
@ -545,9 +562,9 @@ namespace osmium {
* 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).
* @returns Size of the data read from BlobHeader (0 on EOF).
*/
size_t read_blob_header(const char* expected_type) {
int 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))) {
@ -556,29 +573,29 @@ namespace osmium {
uint32_t size = ntohl(size_in_network_byte_order);
if (size > static_cast<uint32_t>(OSMPBF::max_blob_header_size)) {
throw std::runtime_error("Invalid BlobHeader size");
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 std::runtime_error("Read error.");
throw osmium::pbf_error("read error");
}
if (!m_blob_header.ParseFromArray(blob_header_buffer, static_cast<int>(size))) {
throw std::runtime_error("Failed to parse BlobHeader.");
throw osmium::pbf_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).");
throw osmium::pbf_error("blob does not have expected type (OSMHeader in first blob, OSMData in following blobs)");
}
return static_cast<size_t>(m_blob_header.datasize());
return 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")) {
while (int size = read_blob_header("OSMData")) {
DataBlobParser data_blob_parser(size, n, m_input_queue_reader, read_types);
if (m_use_thread_pool) {
@ -627,7 +644,7 @@ namespace osmium {
GOOGLE_PROTOBUF_VERIFY_VERSION;
// handle OSMHeader
size_t size = read_blob_header("OSMHeader");
int size = read_blob_header("OSMHeader");
{
HeaderBlobParser header_blob_parser(size, m_input_queue_reader, m_header);

View File

@ -128,6 +128,7 @@ More complete outlines of real .osm.pbf files can be created using the osmpbf-ou
#include <osmium/osm/tag.hpp>
#include <osmium/osm/timestamp.hpp>
#include <osmium/osm/way.hpp>
#include <osmium/util/cast.hpp>
#include <osmium/visitor.hpp>
namespace osmium {
@ -153,7 +154,7 @@ namespace osmium {
std::string content;
msg.SerializeToString(&content);
pbf_blob.set_raw_size(content.size());
pbf_blob.set_raw_size(static_cast_with_assert<::google::protobuf::int32>(content.size()));
if (use_compression) {
pbf_blob.set_zlib_data(osmium::io::detail::zlib_compress(content));
@ -167,12 +168,12 @@ namespace osmium {
OSMPBF::BlobHeader pbf_blob_header;
pbf_blob_header.set_type(type);
pbf_blob_header.set_datasize(blob_data.size());
pbf_blob_header.set_datasize(static_cast_with_assert<::google::protobuf::int32>(blob_data.size()));
std::string blob_header_data;
pbf_blob_header.SerializeToString(&blob_header_data);
uint32_t sz = htonl(blob_header_data.size());
uint32_t sz = htonl(static_cast_with_assert<uint32_t>(blob_header_data.size()));
// write to output: the 4-byte BlobHeader-Size followed by the BlobHeader followed by the Blob
std::string output;
@ -236,7 +237,7 @@ namespace osmium {
* 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;
static constexpr int64_t buffer_fill_percent = 95;
/**
* protobuf-struct of a HeaderBlock
@ -313,7 +314,7 @@ namespace osmium {
* called once for each object.
*/
uint16_t primitive_block_contents;
uint32_t primitive_block_size;
int primitive_block_size;
// StringTable management
StringTable string_table;
@ -329,7 +330,7 @@ namespace osmium {
Delta<int64_t> m_delta_timestamp;
Delta<int64_t> m_delta_changeset;
Delta<int64_t> m_delta_uid;
Delta<uint32_t> m_delta_user_sid;
Delta<::google::protobuf::int32> m_delta_user_sid;
bool debug;
@ -365,10 +366,8 @@ namespace osmium {
for (int i=0, l=dense->keys_vals_size(); i<l; ++i) {
// map interim string-ids > 0 to real string ids
auto sid = dense->keys_vals(i);
assert(sid >= 0);
assert(sid < std::numeric_limits<osmium::io::detail::StringTable::string_id_type>::max());
if (sid > 0) {
dense->set_keys_vals(i, string_table.map_string_id(static_cast<osmium::io::detail::StringTable::string_id_type>(sid)));
dense->set_keys_vals(i, string_table.map_string_id(sid));
}
}
@ -380,9 +379,7 @@ namespace osmium {
// iterate over all username string-ids
for (int i=0, l=denseinfo->user_sid_size(); i<l; ++i) {
// map interim string-ids > 0 to real string ids
auto usid = denseinfo->user_sid(i);
assert(usid < std::numeric_limits<osmium::io::detail::StringTable::string_id_type>::max());
auto user_sid = string_table.map_string_id(static_cast<osmium::io::detail::StringTable::string_id_type>(usid));
auto user_sid = string_table.map_string_id(denseinfo->user_sid(i));
// delta encode the string-id
denseinfo->set_user_sid(i, m_delta_user_sid.update(user_sid));
@ -411,7 +408,7 @@ namespace osmium {
// 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(); mi<ml; ++mi) {
for (int mi=0; mi < relation->roles_sid_size(); ++mi) {
relation->set_roles_sid(mi, string_table.map_string_id(relation->roles_sid(mi)));
}
}
@ -447,14 +444,14 @@ namespace osmium {
* 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());
return static_cast<int64_t>(std::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<double>(1000) / date_granularity()));
return static_cast<int64_t>(std::round(timestamp * (1000.0 / date_granularity())));
}
/**
@ -570,7 +567,7 @@ namespace osmium {
void check_block_contents_counter() {
if (primitive_block_contents >= max_block_contents) {
store_primitive_block();
} else if (primitive_block_size > (static_cast<uint32_t>(OSMPBF::max_uncompressed_blob_size) * buffer_fill_percent / 100)) {
} else if (primitive_block_size > 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<float>(primitive_block_size) / static_cast<float>(OSMPBF::max_uncompressed_blob_size) * 100.0) << "% of the maximum blob-size" << std::endl;
@ -650,7 +647,7 @@ namespace osmium {
denseinfo->add_changeset(m_delta_changeset.update(node.changeset()));
// copy the user id, delta encoded
denseinfo->add_uid(m_delta_uid.update(node.uid()));
denseinfo->add_uid(static_cast<::google::protobuf::int32>(m_delta_uid.update(node.uid())));
// record the user-name to the interim stringtable and copy the
// interim string-id to the pbf-object
@ -808,7 +805,7 @@ namespace osmium {
// when the resulting file will carry history information, add
// HistoricalInformation as required feature
if (this->m_file.has_multiple_object_versions()) {
if (m_file.has_multiple_object_versions()) {
pbf_header_block.add_required_features("HistoricalInformation");
}

View File

@ -34,15 +34,17 @@ DEALINGS IN THE SOFTWARE.
*/
#include <algorithm>
#include <cstdint>
#include <iterator>
#include <map>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include <osmpbf/osmpbf.h>
#include <osmium/util/cast.hpp>
namespace osmium {
namespace io {
@ -83,12 +85,14 @@ namespace osmium {
* 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;
};
}; // struct string_info
/**
* Interim StringTable, storing all strings that should be written to
@ -123,8 +127,7 @@ namespace osmium {
string_info& info = m_strings[string];
if (info.interim_id == 0) {
++m_size;
assert(m_size < std::numeric_limits<string_id_type>::max());
info.interim_id = static_cast<string_id_type>(m_size);
info.interim_id = static_cast_with_assert<string_id_type>(m_size);
} else {
info.count++;
}
@ -176,6 +179,11 @@ namespace osmium {
return m_id2id_map[interim_id];
}
template <typename T>
string_id_type map_string_id(const T interim_id) const {
return map_string_id(static_cast_with_assert<string_id_type>(interim_id));
}
/**
* Clear the stringtable, preparing for the next block.
*/

View File

@ -74,10 +74,11 @@ namespace osmium {
while (!m_done) {
std::string data {m_decompressor->read()};
if (data.empty()) {
m_done = true;
m_queue.push(std::move(data));
break;
}
m_queue.push(std::move(data));
while (m_queue.size() > 10) {
while (m_queue.size() > 10 && !m_done) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}

View File

@ -37,13 +37,12 @@ DEALINGS IN THE SOFTWARE.
#include <cstddef>
#include <fcntl.h>
#include <string>
//#include <sys/stat.h>
//#include <sys/types.h>
#include <system_error>
#ifndef _MSC_VER
#include <unistd.h>
# include <unistd.h>
#else
#include <io.h>
# include <io.h>
typedef int ssize_t;
#endif
@ -61,11 +60,11 @@ namespace osmium {
/**
* 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.
* is opened 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.
* @returns 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) {
@ -78,7 +77,7 @@ namespace osmium {
} else {
flags |= O_EXCL;
}
#ifdef WIN32
#ifdef _WIN32
flags |= O_BINARY;
#endif
int fd = ::open(filename.c_str(), flags, 0666);
@ -91,9 +90,10 @@ namespace osmium {
/**
* Open file for reading. If the file name is empty or "-", no file
* is open and the stdin file descriptor (0) is returned.
* is opened and the stdin file descriptor (0) is returned.
*
* @return File descriptor of open file.
* @param filename Name of file to be opened.
* @returns File descriptor of open file.
* @throws system_error if the file can't be opened.
*/
inline int open_for_reading(const std::string& filename) {
@ -101,7 +101,7 @@ namespace osmium {
return 0; // stdin
} else {
int flags = O_RDONLY;
#ifdef WIN32
#ifdef _WIN32
flags |= O_BINARY;
#endif
int fd = ::open(filename.c_str(), flags);
@ -112,39 +112,15 @@ namespace osmium {
}
}
/**
* 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<size_t>(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).
* This is just a wrapper around write(2), because write(2) can write less than
* the given number of bytes.
*
* @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.
* @param output_buffer Buffer with data to be written. Must be at least size bytes long.
* @param size Number of bytes to write.
* @throws 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;
@ -157,6 +133,16 @@ namespace osmium {
} while (offset < size);
}
/**
* Writes the given number of bytes from the output_buffer to the file descriptor.
* This is just a wrapper around write(2), because write(2) can write less than
* the given number of bytes.
*
* @param fd File descriptor.
* @param output_buffer Buffer with data to be written. Must be at least size bytes long.
* @param size Number of bytes to write.
* @throws std::system_error On error.
*/
inline void reliable_write(const int fd, const char* output_buffer, const size_t size) {
reliable_write(fd, reinterpret_cast<const unsigned char*>(output_buffer), size);
}

View File

@ -69,9 +69,15 @@ DEALINGS IN THE SOFTWARE.
#include <osmium/osm/types.hpp>
#include <osmium/thread/queue.hpp>
#include <osmium/thread/checked_task.hpp>
#include <osmium/util/cast.hpp>
namespace osmium {
/**
* Exception thrown when the XML parser failed. The exception contains
* information about the place where the error happened and the type of
* error.
*/
struct xml_error : public io_error {
unsigned long line;
@ -120,6 +126,8 @@ namespace osmium {
* 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.
*
* This exception is never seen by user code, it is caught internally.
*/
class ParserIsDone : std::exception {
};
@ -140,7 +148,7 @@ namespace osmium {
ignored_relation,
ignored_changeset,
in_object
};
}; // enum class context
context m_context;
context m_last_context;
@ -168,14 +176,81 @@ namespace osmium {
osmium::thread::Queue<osmium::memory::Buffer>& m_queue;
std::promise<osmium::io::Header>& m_header_promise;
bool m_promise_fulfilled;
osmium::osm_entity_bits::type m_read_types;
size_t m_max_queue_size;
std::atomic<bool>& m_done;
/**
* A C++ wrapper for the Expat parser that makes sure no memory is leaked.
*/
template <class T>
class ExpatXMLParser {
XML_Parser m_parser;
static void XMLCALL start_element_wrapper(void* data, const XML_Char* element, const XML_Char** attrs) {
static_cast<XMLParser*>(data)->start_element(element, attrs);
}
static void XMLCALL end_element_wrapper(void* data, const XML_Char* element) {
static_cast<XMLParser*>(data)->end_element(element);
}
public:
ExpatXMLParser(T* callback_object) :
m_parser(XML_ParserCreate(nullptr)) {
if (!m_parser) {
throw osmium::io_error("Internal error: Can not create parser");
}
XML_SetUserData(m_parser, callback_object);
XML_SetElementHandler(m_parser, start_element_wrapper, end_element_wrapper);
}
ExpatXMLParser(const ExpatXMLParser&) = delete;
ExpatXMLParser(ExpatXMLParser&&) = delete;
ExpatXMLParser& operator=(const ExpatXMLParser&) = delete;
ExpatXMLParser& operator=(ExpatXMLParser&&) = delete;
~ExpatXMLParser() {
XML_ParserFree(m_parser);
}
void operator()(const std::string& data, bool last) {
if (XML_Parse(m_parser, data.data(), static_cast_with_assert<int>(data.size()), last) == XML_STATUS_ERROR) {
throw osmium::xml_error(m_parser);
}
}
}; // class ExpatXMLParser
/**
* A helper class that makes sure a promise is kept. It stores
* a reference to some piece of data and to a promise and, on
* destruction, sets the value of the promise from the data.
*/
template <class T>
class PromiseKeeper {
T& m_data;
std::promise<T>& m_promise;
public:
PromiseKeeper(T& data, std::promise<T>& promise) :
m_data(data),
m_promise(promise) {
}
~PromiseKeeper() {
m_promise.set_value(m_data);
}
}; // class PromiseKeeper
public:
explicit XMLParser(osmium::thread::Queue<std::string>& input_queue, osmium::thread::Queue<osmium::memory::Buffer>& queue, std::promise<osmium::io::Header>& header_promise, osmium::osm_entity_bits::type read_types, std::atomic<bool>& done) :
@ -194,7 +269,6 @@ namespace osmium {
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) {
@ -222,7 +296,6 @@ namespace osmium {
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) {
@ -237,70 +310,45 @@ namespace osmium {
~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));
ExpatXMLParser<XMLParser> parser(this);
PromiseKeeper<osmium::io::Header> promise_keeper(m_header, m_header_promise);
bool last;
do {
std::string data;
m_input_queue.wait_and_pop(data);
last = data.empty();
try {
parser(data, last);
} catch (ParserIsDone&) {
return true;
} catch (...) {
m_queue.push(osmium::memory::Buffer()); // empty buffer to signify eof
throw;
}
m_queue.push(osmium::memory::Buffer()); // empty buffer to signify eof
} catch (ParserIsDone&) {
// intentionally left blank
} while (!last && !m_done);
if (m_buffer.committed() > 0) {
m_queue.push(std::move(m_buffer));
}
XML_ParserFree(parser);
m_queue.push(osmium::memory::Buffer()); // empty buffer to signify eof
return true;
}
private:
static void XMLCALL start_element_wrapper(void* data, const XML_Char* element, const XML_Char** attrs) {
static_cast<XMLParser*>(data)->start_element(element, attrs);
}
static void XMLCALL end_element_wrapper(void* data, const XML_Char* element) {
static_cast<XMLParser*>(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);
object.set_visible(false);
}
osmium::Location location;
for (int count = 0; attrs[count]; count += 2) {
if (!strcmp(attrs[count], "lon")) {
static_cast<osmium::Node&>(object).location().lon(std::atof(attrs[count+1])); // XXX doesn't detect garbage after the number
location.set_lon(std::atof(attrs[count+1])); // XXX doesn't detect garbage after the number
} else if (!strcmp(attrs[count], "lat")) {
static_cast<osmium::Node&>(object).location().lat(std::atof(attrs[count+1])); // XXX doesn't detect garbage after the number
location.set_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 {
@ -308,6 +356,10 @@ namespace osmium {
}
}
if (location && object.type() == osmium::item_type::node) {
static_cast<osmium::Node&>(object).set_location(location);
}
return user;
}
@ -320,13 +372,13 @@ namespace osmium {
osmium::Location max;
for (int count = 0; attrs[count]; count += 2) {
if (!strcmp(attrs[count], "min_lon")) {
min.lon(atof(attrs[count+1]));
min.set_lon(atof(attrs[count+1]));
} else if (!strcmp(attrs[count], "min_lat")) {
min.lat(atof(attrs[count+1]));
min.set_lat(atof(attrs[count+1]));
} else if (!strcmp(attrs[count], "max_lon")) {
max.lon(atof(attrs[count+1]));
max.set_lon(atof(attrs[count+1]));
} else if (!strcmp(attrs[count], "max_lat")) {
max.lat(atof(attrs[count+1]));
max.set_lat(atof(attrs[count+1]));
} else if (!strcmp(attrs[count], "user")) {
user = attrs[count+1];
} else {
@ -350,8 +402,7 @@ namespace osmium {
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) {
} else if (attrs[count][0] == 'v' && attrs[count][1] == 0) {
value = attrs[count+1];
}
}
@ -363,12 +414,8 @@ namespace osmium {
}
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();
}
if (m_read_types == osmium::osm_entity_bits::nothing) {
throw ParserIsDone();
}
}
@ -377,7 +424,7 @@ namespace osmium {
case context::root:
if (!strcmp(element, "osm") || !strcmp(element, "osmChange")) {
if (!strcmp(element, "osmChange")) {
m_header.has_multiple_object_versions(true);
m_header.set_has_multiple_object_versions(true);
}
for (int count = 0; attrs[count]; count += 2) {
if (!strcmp(attrs[count], "version")) {
@ -438,13 +485,13 @@ namespace osmium {
osmium::Location max;
for (int count = 0; attrs[count]; count += 2) {
if (!strcmp(attrs[count], "minlon")) {
min.lon(atof(attrs[count+1]));
min.set_lon(atof(attrs[count+1]));
} else if (!strcmp(attrs[count], "minlat")) {
min.lat(atof(attrs[count+1]));
min.set_lat(atof(attrs[count+1]));
} else if (!strcmp(attrs[count], "maxlon")) {
max.lon(atof(attrs[count+1]));
max.set_lon(atof(attrs[count+1]));
} else if (!strcmp(attrs[count], "maxlat")) {
max.lat(atof(attrs[count+1]));
max.set_lat(atof(attrs[count+1]));
}
}
osmium::Box box;
@ -610,7 +657,7 @@ namespace osmium {
}
}
}; // XMLParser
}; // class XMLParser
class XMLInputFormat : public osmium::io::detail::InputFormat {
@ -639,7 +686,11 @@ namespace osmium {
}
~XMLInputFormat() {
m_done = true;
try {
close();
} catch (...) {
// ignore any exceptions at this point because destructor should not throw
}
}
virtual osmium::io::Header header() override final {
@ -657,6 +708,11 @@ namespace osmium {
return buffer;
}
void close() {
m_done = true;
m_parser_task.close();
}
}; // class XMLInputFormat
namespace {

View File

@ -96,10 +96,13 @@ namespace osmium {
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 NDEBUG
int len =
#endif
#ifndef _MSC_VER
int len = snprintf(buffer, max_size, format, value);
snprintf(buffer, max_size, format, value);
#else
int len = _snprintf(buffer, max_size, format, value);
_snprintf(buffer, max_size, format, value);
#endif
assert(len > 0 && static_cast<size_t>(len) < max_size);
out += buffer;
@ -115,7 +118,7 @@ namespace osmium {
op_create = 1,
op_modify = 2,
op_delete = 3
};
}; // enum class operation
osmium::memory::Buffer m_input_buffer;
@ -257,9 +260,9 @@ namespace osmium {
if (node.location()) {
m_out += " lat=\"";
osmium::Location::coordinate2string(std::back_inserter(m_out), node.location().lat_without_check());
osmium::util::double2string(std::back_inserter(m_out), node.location().lat_without_check(), 7);
m_out += "\" lon=\"";
osmium::Location::coordinate2string(std::back_inserter(m_out), node.location().lon_without_check());
osmium::util::double2string(std::back_inserter(m_out), node.location().lon_without_check(), 7);
m_out += "\"";
}
@ -402,7 +405,7 @@ namespace osmium {
}
void write_buffer(osmium::memory::Buffer&& buffer) override final {
XMLOutputBlock output_block(std::move(buffer), m_write_visible_flag, m_file.is_true("xml_change_format"));
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

View File

@ -50,7 +50,7 @@ namespace osmium {
* Compress data using zlib.
*
* @param input Data to compress.
* @return Compressed data.
* @returns Compressed data.
*/
inline std::string zlib_compress(const std::string& input) {
unsigned long output_size = ::compressBound(input.size());
@ -74,7 +74,7 @@ namespace osmium {
*
* @param input Compressed input data.
* @param raw_size Size of uncompressed data.
* @return Uncompressed data.
* @returns Uncompressed data.
*/
inline std::string zlib_uncompress(const std::string& input, unsigned long raw_size) {
std::string output(raw_size, '\0');

View File

@ -1,319 +1,358 @@
#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 <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 <cstddef>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#include <osmium/io/file_format.hpp>
#include <osmium/io/file_compression.hpp>
#include <osmium/util/options.hpp>
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<std::string> split(const std::string& in, const char delim) {
std::vector<std::string> 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<std::string> 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<std::string> 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
#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 <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 <cstddef>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#include <osmium/io/file_format.hpp>
#include <osmium/io/file_compression.hpp>
#include <osmium/util/options.hpp>
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.
*/
namespace io {
namespace detail {
inline std::vector<std::string> split(const std::string& in, const char delim) {
std::vector<std::string> 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;
const char* m_buffer;
size_t m_buffer_size;
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_buffer(nullptr),
m_buffer_size(0),
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);
}
}
/**
* Create File using buffer pointer and size and type and encoding
* from given format specification.
*
* @param buffer Pointer to buffer with data.
* @param size Size of buffer.
* @param format File format as string. See the description of the
* parse_format() function for details.
*/
explicit File(const char* buffer, size_t size, const std::string& format = "") :
Options(),
m_filename(),
m_buffer(buffer),
m_buffer_size(size),
m_format_string(format) {
default_settings_for_stdinout();
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;
const char* buffer() const noexcept {
return m_buffer;
}
size_t buffer_size() const noexcept {
return m_buffer_size;
}
void parse_format(const std::string& format) {
std::vector<std::string> 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<std::string> 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 noexcept {
return m_file_format;
}
File& set_format(file_format format) noexcept {
m_file_format = format;
return *this;
}
file_compression compression() const noexcept {
return m_file_compression;
}
File& set_compression(file_compression compression) noexcept {
m_file_compression = compression;
return *this;
}
bool has_multiple_object_versions() const noexcept {
return m_has_multiple_object_versions;
}
File& set_has_multiple_object_versions(bool value) noexcept {
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 noexcept {
return m_filename;
}
}; // class File
} // namespace io
} // namespace osmium
#endif // OSMIUM_IO_FILE_HPP

View File

@ -45,6 +45,9 @@ namespace osmium {
bzip2 = 2
};
// avoid g++ false positive
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type"
inline const char* as_string(file_compression compression) {
switch (compression) {
case file_compression::none:
@ -55,6 +58,7 @@ namespace osmium {
return "bzip2";
}
}
#pragma GCC diagnostic pop
template <typename TChar, typename TTraits>
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const file_compression compression) {

View File

@ -47,6 +47,9 @@ namespace osmium {
json = 4
};
// avoid g++ false positive
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type"
inline const char* as_string(file_format format) {
switch (format) {
case file_format::unknown:
@ -61,6 +64,7 @@ namespace osmium {
return "JSON";
}
}
#pragma GCC diagnostic pop
template <typename TChar, typename TTraits>
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const file_format format) {

View File

@ -38,15 +38,52 @@ DEALINGS IN THE SOFTWARE.
#include <stdexcept>
#include <string>
#include <errno.h>
#include <zlib.h>
#include <osmium/io/compression.hpp>
#include <osmium/io/file_compression.hpp>
#include <osmium/util/cast.hpp>
#include <osmium/util/compatibility.hpp>
namespace osmium {
/**
* Exception thrown when there are problems compressing or
* decompressing gzip files.
*/
struct gzip_error : public std::runtime_error {
int gzip_error_code;
int system_errno;
gzip_error(const std::string& what, int error_code) :
std::runtime_error(what),
gzip_error_code(error_code),
system_errno(error_code == Z_ERRNO ? errno : 0) {
}
}; // struct gzip_error
namespace io {
namespace detail {
OSMIUM_NORETURN inline void throw_gzip_error(gzFile gzfile, const char* msg, int zlib_error=0) {
std::string error("gzip error: ");
error += msg;
error += ": ";
int errnum = zlib_error;
if (zlib_error) {
error += std::to_string(zlib_error);
} else {
error += ::gzerror(gzfile, &errnum);
}
throw osmium::gzip_error(error, errnum);
}
} // namespace detail
class GzipCompressor : public Compressor {
gzFile m_gzfile;
@ -57,22 +94,30 @@ namespace osmium {
Compressor(),
m_gzfile(::gzdopen(fd, "w")) {
if (!m_gzfile) {
throw std::runtime_error("initialization of gzip compression failed");
detail::throw_gzip_error(m_gzfile, "write initialization failed");
}
}
~GzipCompressor() override final {
this->close();
close();
}
void write(const std::string& data) override final {
::gzwrite(m_gzfile, data.data(), data.size());
if (!data.empty()) {
int nwrite = ::gzwrite(m_gzfile, data.data(), static_cast_with_assert<unsigned int>(data.size()));
if (nwrite == 0) {
detail::throw_gzip_error(m_gzfile, "write failed");
}
}
}
void close() override final {
if (m_gzfile) {
::gzclose(m_gzfile);
int result = ::gzclose(m_gzfile);
m_gzfile = nullptr;
if (result != Z_OK) {
detail::throw_gzip_error(m_gzfile, "write close failed", result);
}
}
}
@ -88,20 +133,19 @@ namespace osmium {
Decompressor(),
m_gzfile(::gzdopen(fd, "r")) {
if (!m_gzfile) {
throw std::runtime_error("initialization of gzip compression failed");
detail::throw_gzip_error(m_gzfile, "read initialization failed");
}
}
~GzipDecompressor() override final {
this->close();
close();
}
std::string read() override final {
std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0');
int nread = ::gzread(m_gzfile, const_cast<char*>(buffer.data()), buffer.size());
int nread = ::gzread(m_gzfile, const_cast<char*>(buffer.data()), static_cast_with_assert<unsigned int>(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");
detail::throw_gzip_error(m_gzfile, "read failed");
}
buffer.resize(static_cast<std::string::size_type>(nread));
return buffer;
@ -109,18 +153,80 @@ namespace osmium {
void close() override final {
if (m_gzfile) {
::gzclose(m_gzfile);
int result = ::gzclose(m_gzfile);
m_gzfile = nullptr;
if (result != Z_OK) {
detail::throw_gzip_error(m_gzfile, "read close failed", result);
}
}
}
}; // class GzipDecompressor
class GzipBufferDecompressor : public Decompressor {
const char* m_buffer;
size_t m_buffer_size;
z_stream m_zstream;
public:
GzipBufferDecompressor(const char* buffer, size_t size) :
m_buffer(buffer),
m_buffer_size(size),
m_zstream() {
m_zstream.next_in = reinterpret_cast<unsigned char*>(const_cast<char*>(buffer));
m_zstream.avail_in = static_cast_with_assert<unsigned int>(size);
int result = inflateInit2(&m_zstream, MAX_WBITS | 32);
if (result != Z_OK) {
std::string message("gzip error: decompression init failed: ");
if (m_zstream.msg) {
message.append(m_zstream.msg);
}
throw osmium::gzip_error(message, result);
}
}
~GzipBufferDecompressor() override final {
inflateEnd(&m_zstream);
}
std::string read() override final {
if (!m_buffer) {
return std::string();
}
const size_t buffer_size = 10240;
std::string output(buffer_size, '\0');
m_zstream.next_out = reinterpret_cast<unsigned char*>(const_cast<char*>(output.data()));
m_zstream.avail_out = buffer_size;
int result = inflate(&m_zstream, Z_SYNC_FLUSH);
if (result != Z_OK) {
m_buffer = nullptr;
m_buffer_size = 0;
}
if (result != Z_OK && result != Z_STREAM_END) {
std::string message("gzip error: inflate failed: ");
if (m_zstream.msg) {
message.append(m_zstream.msg);
}
throw osmium::gzip_error(message, result);
}
output.resize(static_cast<unsigned long>(m_zstream.next_out - reinterpret_cast<const unsigned char*>(output.data())));
return output;
}
}; // class GzipBufferDecompressor
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); }
[](int fd) { return new osmium::io::GzipDecompressor(fd); },
[](const char* buffer, size_t size) { return new osmium::io::GzipBufferDecompressor(buffer, size); }
);
} // anonymous namespace

View File

@ -73,15 +73,15 @@ namespace osmium {
~Header() = default;
std::vector<osmium::Box>& boxes() {
std::vector<osmium::Box>& boxes() noexcept {
return m_boxes;
}
const std::vector<osmium::Box>& boxes() const {
const std::vector<osmium::Box>& boxes() const noexcept {
return m_boxes;
}
Header& boxes(const std::vector<osmium::Box>& boxes) {
Header& boxes(const std::vector<osmium::Box>& boxes) noexcept {
m_boxes = boxes;
return *this;
}
@ -104,12 +104,12 @@ namespace osmium {
return *this;
}
bool has_multiple_object_versions() const {
bool has_multiple_object_versions() const noexcept {
return m_has_multiple_object_versions;
}
Header& has_multiple_object_versions(bool h) {
m_has_multiple_object_versions = h;
Header& set_has_multiple_object_versions(bool value) noexcept {
m_has_multiple_object_versions = value;
return *this;
}

View File

@ -89,7 +89,7 @@ namespace osmium {
}
// end iterator
InputIterator() :
InputIterator() noexcept :
m_source(nullptr) {
}
@ -110,13 +110,13 @@ namespace osmium {
return tmp;
}
bool operator==(const InputIterator& rhs) const {
bool operator==(const InputIterator& rhs) const noexcept {
return m_source == rhs.m_source &&
m_buffer == rhs.m_buffer &&
m_iter == rhs.m_iter;
}
bool operator!=(const InputIterator& rhs) const {
bool operator!=(const InputIterator& rhs) const noexcept {
return !(*this == rhs);
}

View File

@ -1,114 +1,116 @@
#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 <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 <cstddef>
#include <iterator>
#include <memory>
#include <utility>
#include <osmium/memory/buffer.hpp>
#include <osmium/osm/diff_object.hpp>
namespace osmium {
namespace memory {
class Item;
} // namespace memory
namespace io {
template <class TDest>
class OutputIterator : public std::iterator<std::output_iterator_tag, osmium::memory::Item> {
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<buffer_wrapper> 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_wrapper>(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
#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 <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 <cstddef>
#include <iterator>
#include <memory>
#include <utility>
#include <osmium/memory/buffer.hpp>
#include <osmium/osm/diff_object.hpp>
namespace osmium {
namespace memory {
class Item;
} // namespace memory
namespace io {
template <class TDest>
class OutputIterator : public std::iterator<std::output_iterator_tag, osmium::memory::Item> {
struct buffer_wrapper {
osmium::memory::Buffer buffer;
buffer_wrapper(size_t buffer_size) :
buffer(buffer_size, osmium::memory::Buffer::auto_grow::no) {
}
}; // struct buffer_wrapper
static constexpr size_t default_buffer_size = 10 * 1024 * 1024;
TDest* m_destination;
std::shared_ptr<buffer_wrapper> 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_wrapper>(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::buffer_is_full&) {
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

View File

@ -41,15 +41,16 @@ DEALINGS IN THE SOFTWARE.
#include <string>
#include <system_error>
#include <thread>
#ifndef _WIN32
#include <sys/wait.h>
#endif
#ifndef _MSC_VER
#include <unistd.h>
#else
#endif
#include <utility>
#ifndef _WIN32
# include <sys/wait.h>
#endif
#ifndef _MSC_VER
# include <unistd.h>
#endif
#include <osmium/io/compression.hpp>
#include <osmium/io/detail/input_format.hpp>
#include <osmium/io/detail/read_thread.hpp>
@ -95,7 +96,7 @@ namespace osmium {
*
* @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.
* @returns 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) {
@ -140,7 +141,7 @@ namespace osmium {
* are opened by executing the "curl" program (which must be installed)
* and reading from its output.
*
* @return File descriptor of open file or pipe.
* @returns 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) {
@ -173,7 +174,9 @@ namespace osmium {
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_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_input(osmium::io::detail::InputFormatFactory::instance().create_input(m_file, m_read_which_entities, m_input_queue)) {
}
@ -190,7 +193,11 @@ namespace osmium {
Reader& operator=(const Reader&) = delete;
~Reader() {
close();
try {
close();
}
catch (...) {
}
}
/**
@ -233,7 +240,10 @@ namespace osmium {
/**
* Reads the next buffer from the input. An invalid buffer signals
* end-of-file. Do not call read() after the end-of-file.
* end-of-file. After end-of-file all read() calls will return an
* invalid buffer. An invalid buffer is also always returned if
* osmium::osm_entity_bits::nothing was set when the Reader was
* constructed.
*
* @returns Buffer.
* @throws Some form of std::runtime_error if there is an error.
@ -243,12 +253,25 @@ namespace osmium {
// it in this (the main) thread.
m_read_task.check_for_exception();
if (m_read_which_entities == osmium::osm_entity_bits::nothing) {
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
// always get an empty buffer here.
return osmium::memory::Buffer();
}
return m_input->read();
osmium::memory::Buffer buffer = m_input->read();
if (!buffer) {
m_input_done = true;
}
return buffer;
}
/**
* 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() {
return m_input_done;
}
}; // class Reader

View File

@ -90,6 +90,7 @@ namespace osmium {
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()) {
assert(!m_file.buffer());
m_output->write_header(header);
}
@ -121,7 +122,7 @@ namespace osmium {
}
/**
* Flush writes to output file and close it. If you do not
* Flush writes to output file and closes 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.

View File

@ -49,17 +49,24 @@ DEALINGS IN THE SOFTWARE.
namespace osmium {
/**
* Exception thrown by the osmium::memory::Buffer class when somebody tries
* to write data into a buffer and it doesn't fit. Buffers with internal
* memory management will not throw this exception, but increase their size.
*/
struct buffer_is_full : public std::runtime_error {
buffer_is_full() :
std::runtime_error("Osmium buffer is full") {
}
}; // struct buffer_is_full
/**
* @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.
@ -80,7 +87,7 @@ namespace osmium {
* 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.
* By default, if a buffer gets full it will throw a buffer_is_full exception.
* You can use the set_full_callback() method to set a callback functor
* which will be called instead of throwing an exception.
*/
@ -91,7 +98,7 @@ namespace osmium {
enum class auto_grow : bool {
yes = true,
no = false
};
}; // enum class auto_grow
private:
@ -112,7 +119,7 @@ namespace osmium {
* 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() :
Buffer() noexcept :
m_memory(),
m_data(nullptr),
m_capacity(0),
@ -126,7 +133,7 @@ namespace osmium {
*
* @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.
* @throws std::invalid_argument When the size isn't a multiple of the alignment.
*/
explicit Buffer(unsigned char* data, size_t size) :
m_memory(),
@ -146,7 +153,7 @@ namespace osmium {
* @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.
* @throws 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(),
@ -193,21 +200,21 @@ namespace osmium {
/**
* Return a pointer to data inside the buffer.
*/
unsigned char* data() const {
unsigned char* data() const noexcept {
return m_data;
}
/**
* Returns the capacity of the buffer, ie how many bytes it can contain.
*/
size_t capacity() const {
size_t capacity() const noexcept {
return m_capacity;
}
/**
* Returns the number of bytes already filled in this buffer.
*/
size_t committed() const {
size_t committed() const noexcept {
return m_committed;
}
@ -215,7 +222,7 @@ namespace osmium {
* Returns the number of bytes currently filled in this buffer that
* are not yet committed.
*/
size_t written() const {
size_t written() const noexcept {
return m_written;
}
@ -223,13 +230,13 @@ namespace osmium {
* This tests if the current state of the buffer is aligned
* properly. Can be used for asserts.
*/
bool is_aligned() const {
bool is_aligned() const noexcept {
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.
* instead of throwing buffer_is_full.
*/
void set_full_callback(std::function<void(Buffer&)> full) {
m_full = full;
@ -260,7 +267,7 @@ namespace osmium {
/**
* Mark currently written bytes in the buffer as committed.
*
* @return Last number of committed bytes before this commit.
* @returns Last number of committed bytes before this commit.
*/
size_t commit() {
assert(is_aligned());
@ -280,7 +287,7 @@ namespace osmium {
/**
* Clear the buffer.
*
* @return Number of bytes in the buffer before it was cleared.
* @returns Number of bytes in the buffer before it was cleared.
*/
size_t clear() {
const size_t committed = m_committed;
@ -293,7 +300,7 @@ namespace osmium {
* 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.
* @returns Reference of given type pointing to the data in the buffer.
*/
template <class T>
T& get(const size_t offset) const {
@ -317,13 +324,13 @@ namespace osmium {
* * 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.
* * Else the buffer_is_full exception is thrown.
*
* @param size Number of bytes to reserve.
* @return Pointer to reserved space. Note that this pointer is
* @returns 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.
* @throws osmium::buffer_is_full Might be thrown if the buffer is full.
*/
unsigned char* reserve_space(const size_t size) {
if (m_written + size > m_capacity) {
@ -337,7 +344,7 @@ namespace osmium {
}
grow(new_capacity);
} else {
throw BufferIsFull();
throw osmium::buffer_is_full();
}
}
unsigned char* data = &m_data[m_written];
@ -354,7 +361,7 @@ namespace osmium {
*
* @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.
* @returns Reference to newly copied data in the buffer.
*/
template <class T>
T& add_item(const T& item) {
@ -483,6 +490,10 @@ namespace osmium {
*/
template <class TCallbackClass>
void purge_removed(TCallbackClass* callback) {
if (begin() == end()) {
return;
}
iterator it_write = begin();
iterator next;
@ -490,29 +501,29 @@ namespace osmium {
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<size_t>(it_read->data() - data());
size_t new_offset = static_cast<size_t>(it_write->data() - data());
assert(it_read.data() >= data());
assert(it_write.data() >= data());
size_t old_offset = static_cast<size_t>(it_read.data() - data());
size_t new_offset = static_cast<size_t>(it_write.data() - data());
callback->moving_in_buffer(old_offset, new_offset);
std::memmove(it_write->data(), it_read->data(), it_read->padded_size());
std::memmove(it_write.data(), it_read.data(), it_read->padded_size());
}
++it_write;
it_write.advance_once();
}
}
assert(it_write->data() >= data());
m_written = static_cast<size_t>(it_write->data() - data());
assert(it_write.data() >= data());
m_written = static_cast<size_t>(it_write.data() - data());
m_committed = m_written;
}
}; // class Buffer
inline bool operator==(const Buffer& lhs, const Buffer& rhs) {
inline bool operator==(const Buffer& lhs, const Buffer& rhs) noexcept {
return lhs.data() == rhs.data() && lhs.capacity() == rhs.capacity() && lhs.committed() == rhs.committed();
}
inline bool operator!=(const Buffer& lhs, const Buffer& rhs) {
inline bool operator!=(const Buffer& lhs, const Buffer& rhs) noexcept {
return ! (lhs == rhs);
}

View File

@ -1,153 +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 <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 <iterator>
#include <iosfwd>
#include <type_traits>
#include <osmium/memory/item.hpp>
namespace osmium {
namespace memory {
template <class TMember>
class CollectionIterator : public std::iterator<std::forward_iterator_tag, TMember> {
// 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<std::is_const<TMember>::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<TMember>& operator++() {
m_data = reinterpret_cast<TMember*>(m_data)->next();
return *static_cast<CollectionIterator<TMember>*>(this);
}
CollectionIterator<TMember> operator++(int) {
CollectionIterator<TMember> tmp(*this);
operator++();
return tmp;
}
bool operator==(const CollectionIterator<TMember>& rhs) const {
return m_data == rhs.m_data;
}
bool operator!=(const CollectionIterator<TMember>& rhs) const {
return m_data != rhs.m_data;
}
unsigned char* data() const {
return m_data;
}
TMember& operator*() const {
return *reinterpret_cast<TMember*>(m_data);
}
TMember* operator->() const {
return reinterpret_cast<TMember*>(m_data);
}
template <typename TChar, typename TTraits>
friend std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const CollectionIterator<TMember>& iter) {
return out << static_cast<void*>(iter.m_data);
}
}; // class CollectionIterator
template <class TMember, osmium::item_type TCollectionItemType>
class Collection : public Item {
public:
typedef CollectionIterator<TMember> iterator;
typedef CollectionIterator<const TMember> const_iterator;
typedef TMember value_type;
static constexpr osmium::item_type itemtype = TCollectionItemType;
Collection() :
Item(sizeof(Collection<TMember, TCollectionItemType>), TCollectionItemType) {
}
bool empty() const {
return sizeof(Collection<TMember, TCollectionItemType>) == byte_size();
}
iterator begin() {
return iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
}
iterator end() {
return iterator(data() + byte_size());
}
const_iterator cbegin() const {
return const_iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
}
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
#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 <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 <iterator>
#include <iosfwd>
#include <type_traits>
#include <osmium/memory/item.hpp>
namespace osmium {
namespace memory {
template <class TMember>
class CollectionIterator : public std::iterator<std::forward_iterator_tag, TMember> {
// 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<std::is_const<TMember>::value, const unsigned char*, unsigned char*>::type data_type;
data_type m_data;
public:
CollectionIterator() noexcept :
m_data(nullptr) {
}
CollectionIterator(data_type data) noexcept :
m_data(data) {
}
CollectionIterator<TMember>& operator++() {
m_data = reinterpret_cast<TMember*>(m_data)->next();
return *static_cast<CollectionIterator<TMember>*>(this);
}
CollectionIterator<TMember> operator++(int) {
CollectionIterator<TMember> tmp(*this);
operator++();
return tmp;
}
bool operator==(const CollectionIterator<TMember>& rhs) const noexcept {
return m_data == rhs.m_data;
}
bool operator!=(const CollectionIterator<TMember>& rhs) const noexcept {
return m_data != rhs.m_data;
}
unsigned char* data() const noexcept {
return m_data;
}
TMember& operator*() const {
return *reinterpret_cast<TMember*>(m_data);
}
TMember* operator->() const {
return reinterpret_cast<TMember*>(m_data);
}
template <typename TChar, typename TTraits>
friend std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const CollectionIterator<TMember>& iter) {
return out << static_cast<const void*>(iter.m_data);
}
}; // class CollectionIterator
template <class TMember, osmium::item_type TCollectionItemType>
class Collection : public Item {
public:
typedef CollectionIterator<TMember> iterator;
typedef CollectionIterator<const TMember> const_iterator;
typedef TMember value_type;
static constexpr osmium::item_type itemtype = TCollectionItemType;
Collection() :
Item(sizeof(Collection<TMember, TCollectionItemType>), TCollectionItemType) {
}
bool empty() const {
return sizeof(Collection<TMember, TCollectionItemType>) == byte_size();
}
iterator begin() {
return iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
}
iterator end() {
return iterator(data() + byte_size());
}
const_iterator cbegin() const {
return const_iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
}
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

View File

@ -52,11 +52,11 @@ namespace osmium {
// align datastructures to this many bytes
constexpr item_size_type align_bytes = 8;
inline size_t padded_length(size_t length) {
inline size_t padded_length(size_t length) noexcept {
return (length + align_bytes - 1) & ~(align_bytes - 1);
}
inline item_size_type padded_length(item_size_type length) {
inline item_size_type padded_length(item_size_type length) noexcept {
return (length + align_bytes - 1) & ~(align_bytes - 1);
}
@ -85,15 +85,15 @@ namespace osmium {
public:
unsigned char* data() {
unsigned char* data() noexcept {
return reinterpret_cast<unsigned char*>(this);
}
const unsigned char* data() const {
const unsigned char* data() const noexcept {
return reinterpret_cast<const unsigned char*>(this);
}
};
}; // class ItemHelper
} // namespace detail
@ -112,22 +112,14 @@ namespace osmium {
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) {
Item& add_size(const item_size_type size) noexcept {
m_size += size;
return *this;
}
protected:
explicit Item(item_size_type size=0, item_type type=item_type()) :
explicit Item(item_size_type size=0, item_type type=item_type()) noexcept :
m_size(size),
m_type(type),
m_removed(false) {
@ -139,14 +131,22 @@ namespace osmium {
Item& operator=(const Item&) = delete;
Item& operator=(Item&&) = delete;
Item& type(const item_type item_type) {
Item& set_type(const item_type item_type) noexcept {
m_type = item_type;
return *this;
}
public:
item_size_type byte_size() const {
unsigned char* next() noexcept {
return data() + padded_size();
}
const unsigned char* next() const noexcept {
return data() + padded_size();
}
item_size_type byte_size() const noexcept {
return m_size;
}
@ -154,15 +154,15 @@ namespace osmium {
return padded_length(m_size);
}
item_type type() const {
item_type type() const noexcept {
return m_type;
}
bool removed() const {
bool removed() const noexcept {
return m_removed;
}
void removed(bool removed) {
void set_removed(bool removed) noexcept {
m_removed = removed;
}

View File

@ -1,181 +1,234 @@
#ifndef OSMIUM_ITEM_ITERATOR_HPP
#define OSMIUM_ITEM_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 <cassert>
#include <iterator>
#include <iosfwd>
#include <type_traits>
#include <osmium/memory/item.hpp>
#include <osmium/osm.hpp>
#include <osmium/osm/item_type.hpp>
namespace osmium {
namespace memory {
namespace detail {
template <class T>
inline bool type_is_compatible(osmium::item_type) {
return true;
}
template <>
inline bool type_is_compatible<osmium::Node>(osmium::item_type t) {
return t == osmium::item_type::node;
}
template <>
inline bool type_is_compatible<osmium::Way>(osmium::item_type t) {
return t == osmium::item_type::way;
}
template <>
inline bool type_is_compatible<osmium::Relation>(osmium::item_type t) {
return t == osmium::item_type::relation;
}
template <>
inline bool type_is_compatible<osmium::Area>(osmium::item_type t) {
return t == osmium::item_type::area;
}
template <>
inline bool type_is_compatible<osmium::Changeset>(osmium::item_type t) {
return t == osmium::item_type::changeset;
}
template <>
inline bool type_is_compatible<osmium::OSMObject>(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::OSMEntity>(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 TMember>
class ItemIterator : public std::iterator<std::forward_iterator_tag, TMember> {
static_assert(std::is_base_of<osmium::memory::Item, TMember>::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<std::is_const<TMember>::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<typename std::remove_const<TMember>::type>(reinterpret_cast<const osmium::memory::Item*>(m_data)->type())) {
m_data = reinterpret_cast<TMember*>(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<TMember>& operator++() {
assert(m_data);
assert(m_data != m_end);
m_data = reinterpret_cast<TMember*>(m_data)->next();
advance_to_next_item_of_right_type();
return *static_cast<ItemIterator<TMember>*>(this);
}
ItemIterator<TMember> operator++(int) {
ItemIterator<TMember> tmp(*this);
operator++();
return tmp;
}
bool operator==(const ItemIterator<TMember>& rhs) const {
return m_data == rhs.m_data && m_end == rhs.m_end;
}
bool operator!=(const ItemIterator<TMember>& 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<TMember*>(m_data);
}
TMember* operator->() const {
assert(m_data);
assert(m_data != m_end);
return reinterpret_cast<TMember*>(m_data);
}
explicit operator bool() const {
return m_data != nullptr;
}
template <typename TChar, typename TTraits>
friend std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const ItemIterator<TMember>& iter) {
return out << static_cast<void*>(iter.m_data);
}
}; // class ItemIterator
} // namespace memory
} // namespace osmium
#endif // OSMIUM_ITEM_ITERATOR_HPP
#ifndef OSMIUM_ITEM_ITERATOR_HPP
#define OSMIUM_ITEM_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 <cassert>
#include <iterator>
#include <iosfwd>
#include <type_traits>
#include <osmium/memory/item.hpp>
#include <osmium/osm/item_type.hpp>
namespace osmium {
class Node;
class Way;
class Relation;
class Area;
class Changeset;
class OSMObject;
class OSMEntity;
class TagList;
class WayNodeList;
class RelationMemberList;
class InnerRing;
class OuterRing;
namespace memory {
namespace detail {
template <class T>
inline bool type_is_compatible(osmium::item_type) noexcept {
return true;
}
template <>
inline bool type_is_compatible<osmium::Node>(osmium::item_type t) noexcept {
return t == osmium::item_type::node;
}
template <>
inline bool type_is_compatible<osmium::Way>(osmium::item_type t) noexcept {
return t == osmium::item_type::way;
}
template <>
inline bool type_is_compatible<osmium::Relation>(osmium::item_type t) noexcept {
return t == osmium::item_type::relation;
}
template <>
inline bool type_is_compatible<osmium::Area>(osmium::item_type t) noexcept {
return t == osmium::item_type::area;
}
template <>
inline bool type_is_compatible<osmium::Changeset>(osmium::item_type t) noexcept {
return t == osmium::item_type::changeset;
}
template <>
inline bool type_is_compatible<osmium::OSMObject>(osmium::item_type t) noexcept {
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::OSMEntity>(osmium::item_type t) noexcept {
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;
}
template <>
inline bool type_is_compatible<osmium::TagList>(osmium::item_type t) noexcept {
return t == osmium::item_type::tag_list;
}
template <>
inline bool type_is_compatible<osmium::WayNodeList>(osmium::item_type t) noexcept {
return t == osmium::item_type::way_node_list;
}
template <>
inline bool type_is_compatible<osmium::RelationMemberList>(osmium::item_type t) noexcept {
return t == osmium::item_type::relation_member_list || t == osmium::item_type::relation_member_list_with_full_members;
}
template <>
inline bool type_is_compatible<osmium::OuterRing>(osmium::item_type t) noexcept {
return t == osmium::item_type::outer_ring;
}
template <>
inline bool type_is_compatible<osmium::InnerRing>(osmium::item_type t) noexcept {
return t == osmium::item_type::inner_ring;
}
} // namespace detail
template <class TMember>
class ItemIterator : public std::iterator<std::forward_iterator_tag, TMember> {
static_assert(std::is_base_of<osmium::memory::Item, TMember>::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<std::is_const<TMember>::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<typename std::remove_const<TMember>::type>(reinterpret_cast<const osmium::memory::Item*>(m_data)->type())) {
m_data = reinterpret_cast<TMember*>(m_data)->next();
}
}
public:
ItemIterator() noexcept :
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();
}
template <class T>
ItemIterator<T> cast() const {
return ItemIterator<T>(m_data, m_end);
}
ItemIterator<TMember>& operator++() {
assert(m_data);
assert(m_data != m_end);
m_data = reinterpret_cast<TMember*>(m_data)->next();
advance_to_next_item_of_right_type();
return *static_cast<ItemIterator<TMember>*>(this);
}
/**
* Like operator++() but will NOT skip items of unwanted
* types. Do not use this unless you know what you are
* doing.
*/
ItemIterator<TMember>& advance_once() {
assert(m_data);
assert(m_data != m_end);
m_data = reinterpret_cast<TMember*>(m_data)->next();
return *static_cast<ItemIterator<TMember>*>(this);
}
ItemIterator<TMember> operator++(int) {
ItemIterator<TMember> tmp(*this);
operator++();
return tmp;
}
bool operator==(const ItemIterator<TMember>& rhs) const {
return m_data == rhs.m_data && m_end == rhs.m_end;
}
bool operator!=(const ItemIterator<TMember>& rhs) const {
return !(*this == rhs);
}
unsigned char* data() const {
assert(m_data);
return m_data;
}
TMember& operator*() const {
assert(m_data);
assert(m_data != m_end);
return *reinterpret_cast<TMember*>(m_data);
}
TMember* operator->() const {
assert(m_data);
assert(m_data != m_end);
return reinterpret_cast<TMember*>(m_data);
}
explicit operator bool() const {
return m_data != nullptr;
}
template <typename TChar, typename TTraits>
friend std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const ItemIterator<TMember>& iter) {
return out << static_cast<void*>(iter.m_data);
}
}; // class ItemIterator
} // namespace memory
} // namespace osmium
#endif // OSMIUM_ITEM_ITERATOR_HPP

View File

@ -1,112 +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 <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 <algorithm>
#include <utility>
#include <vector>
#include <boost/iterator/indirect_iterator.hpp>
#include <osmium/handler.hpp>
#include <osmium/memory/item.hpp>
#include <osmium/osm/object.hpp>
// 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<osmium::OSMObject*> m_objects;
public:
typedef boost::indirect_iterator<std::vector<osmium::OSMObject*>::iterator, osmium::OSMObject> iterator;
typedef boost::indirect_iterator<std::vector<osmium::OSMObject*>::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 <class TCompare>
void sort(TCompare&& compare) {
std::sort(m_objects.begin(), m_objects.end(), std::forward<TCompare>(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
#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 <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 <algorithm>
#include <utility>
#include <vector>
#include <boost/iterator/indirect_iterator.hpp>
#include <osmium/handler.hpp>
#include <osmium/memory/item.hpp>
#include <osmium/osm/object.hpp>
// 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<osmium::OSMObject*> m_objects;
public:
typedef boost::indirect_iterator<std::vector<osmium::OSMObject*>::iterator, osmium::OSMObject> iterator;
typedef boost::indirect_iterator<std::vector<osmium::OSMObject*>::const_iterator, const osmium::OSMObject> const_iterator;
ObjectPointerCollection() noexcept :
m_objects() {
}
void osm_object(osmium::OSMObject& object) {
m_objects.push_back(&object);
}
/**
* Sort objects according to the given order functor.
*/
template <class TCompare>
void sort(TCompare&& compare) {
std::sort(m_objects.begin(), m_objects.end(), std::forward<TCompare>(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

View File

@ -33,6 +33,7 @@ DEALINGS IN THE SOFTWARE.
*/
#include <cassert>
#include <cstdlib>
#include <utility>
@ -123,7 +124,7 @@ namespace osmium {
* Was this area created from a way? (In contrast to areas
* created from a relation and their members.)
*/
bool from_way() const {
bool from_way() const noexcept {
return (positive_id() & 0x1) == 0;
}
@ -148,7 +149,19 @@ namespace osmium {
case osmium::item_type::inner_ring:
++counter.second;
break;
default:
case osmium::item_type::tag_list:
// ignore tags
break;
case osmium::item_type::undefined:
case osmium::item_type::node:
case osmium::item_type::way:
case osmium::item_type::relation:
case osmium::item_type::area:
case osmium::item_type::changeset:
case osmium::item_type::way_node_list:
case osmium::item_type::relation_member_list:
case osmium::item_type::relation_member_list_with_full_members:
assert(false && "Children of Area can only be outer/inner_ring and tag_list.");
break;
}
}
@ -163,6 +176,14 @@ namespace osmium {
return num_rings().first > 1;
}
osmium::memory::ItemIterator<const osmium::InnerRing> inner_ring_cbegin(const osmium::memory::ItemIterator<const osmium::OuterRing>& it) const {
return it.cast<const osmium::InnerRing>();
}
osmium::memory::ItemIterator<const osmium::InnerRing> inner_ring_cend(const osmium::memory::ItemIterator<const osmium::OuterRing>& it) const {
return std::next(it).cast<const osmium::InnerRing>();
}
}; // class Area
static_assert(sizeof(Area) % osmium::memory::align_bytes == 0, "Class osmium::Area has wrong size to be aligned properly!");

View File

@ -54,7 +54,7 @@ namespace osmium {
* Create undefined Box. Use the extend() function
* to add actual bounds.
*/
constexpr Box() :
constexpr Box() noexcept :
m_bottom_left(),
m_top_right() {
}
@ -83,16 +83,16 @@ namespace osmium {
if (location) {
if (m_bottom_left) {
if (location.x() < m_bottom_left.x()) {
m_bottom_left.x(location.x());
m_bottom_left.set_x(location.x());
}
if (location.x() > m_top_right.x()) {
m_top_right.x(location.x());
m_top_right.set_x(location.x());
}
if (location.y() < m_bottom_left.y()) {
m_bottom_left.y(location.y());
m_bottom_left.set_y(location.y());
}
if (location.y() > m_top_right.y()) {
m_top_right.y(location.y());
m_top_right.set_y(location.y());
}
} else {
m_bottom_left = location;

View File

@ -52,8 +52,11 @@ namespace osmium {
}
/**
* An OSM Changeset is of a group of changes made by a single user over a
* short period of time.
* \brief An OSM Changeset, a group of changes made by a single user over
* a short period of time.
*
* You can not create Changeset objects directly. Use the ChangesetBuilder
* class to create Changesets in a Buffer.
*/
class Changeset : public osmium::OSMEntity {
@ -71,7 +74,7 @@ namespace osmium {
OSMEntity(sizeof(Changeset), osmium::item_type::changeset) {
}
void user_size(string_size_type size) {
void set_user_size(string_size_type size) {
m_user_size = size;
}
@ -83,30 +86,6 @@ namespace osmium {
return data() + osmium::memory::padded_length(sizeof(Changeset) + m_user_size);
}
template <class T>
T& subitem_of_type() {
for (iterator it = begin(); it != end(); ++it) {
if (it->type() == T::itemtype) {
return reinterpret_cast<T&>(*it);
}
}
static T subitem;
return subitem;
}
template <class T>
const T& subitem_of_type() const {
for (const_iterator it = cbegin(); it != cend(); ++it) {
if (it->type() == T::itemtype) {
return reinterpret_cast<const T&>(*it);
}
}
static const T subitem;
return subitem;
}
public:
/// Get ID of this changeset
@ -117,9 +96,10 @@ namespace osmium {
/**
* Set ID of this changeset
*
* @return Reference to changeset to make calls chainable.
* @param id The id.
* @returns Reference to changeset to make calls chainable.
*/
Changeset& id(changeset_id_type id) noexcept {
Changeset& set_id(changeset_id_type id) noexcept {
m_id = id;
return *this;
}
@ -127,10 +107,11 @@ namespace osmium {
/**
* Set ID of this changeset.
*
* @return Reference to object to make calls chainable.
* @param id The id.
* @returns Reference to object to make calls chainable.
*/
Changeset& id(const char* id) {
return this->id(osmium::string_to_changeset_id(id));
Changeset& set_id(const char* id) {
return set_id(osmium::string_to_changeset_id(id));
}
/// Get user id.
@ -141,31 +122,34 @@ namespace osmium {
/**
* Set user id.
*
* @return Reference to changeset to make calls chainable.
* @param uid The user id.
* @returns Reference to changeset to make calls chainable.
*/
Changeset& uid(user_id_type uid) noexcept {
Changeset& set_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.
* Set user id to given uid or to 0 (anonymous user) if the given
* uid is smaller than 0.
*
* @return Reference to changeset to make calls chainable.
* @param uid The user id.
* @returns Reference to changeset to make calls chainable.
*/
Changeset& uid_from_signed(signed_user_id_type uid) noexcept {
Changeset& set_uid_from_signed(signed_user_id_type uid) noexcept {
m_uid = uid < 0 ? 0 : static_cast<user_id_type>(uid);
return *this;
}
/**
* Set user id.
* Set user id to given uid or to 0 (anonymous user) if the given
* uid is smaller than 0.
*
* @return Reference to changeset to make calls chainable.
* @returns Reference to changeset to make calls chainable.
*/
Changeset& uid(const char* uid) {
return this->uid_from_signed(string_to_user_id(uid));
Changeset& set_uid(const char* uid) {
return set_uid_from_signed(string_to_user_id(uid));
}
/// Is this user anonymous?
@ -181,17 +165,19 @@ namespace osmium {
/**
* Get timestamp when this changeset was closed.
*
* This will return the empty Timestamp when the
* changeset is not yet closed.
* @returns Timestamp. Will return the empty Timestamp when the
* changeset is not yet closed.
*/
osmium::Timestamp closed_at() const noexcept {
return m_closed_at;
}
/// Is this changeset open?
bool open() const noexcept {
return m_closed_at == osmium::Timestamp();
}
/// Is this changeset closed?
bool closed() const noexcept {
return !open();
}
@ -200,9 +186,9 @@ namespace osmium {
* Set the timestamp when this changeset was created.
*
* @param timestamp Timestamp
* @return Reference to changeset to make calls chainable.
* @returns Reference to changeset to make calls chainable.
*/
Changeset& created_at(const osmium::Timestamp timestamp) {
Changeset& set_created_at(const osmium::Timestamp timestamp) {
m_created_at = timestamp;
return *this;
}
@ -211,30 +197,43 @@ namespace osmium {
* Set the timestamp when this changeset was closed.
*
* @param timestamp Timestamp
* @return Reference to changeset to make calls chainable.
* @returns Reference to changeset to make calls chainable.
*/
Changeset& closed_at(const osmium::Timestamp timestamp) {
Changeset& set_closed_at(const osmium::Timestamp timestamp) {
m_closed_at = timestamp;
return *this;
}
/// Get the number of changes in this changeset
num_changes_type num_changes() const noexcept {
return m_num_changes;
}
Changeset& num_changes(num_changes_type num_changes) noexcept {
/// Set the number of changes in this changeset
Changeset& set_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));
/// Set the number of changes in this changeset
Changeset& set_num_changes(const char* num_changes) noexcept {
return set_num_changes(osmium::string_to_num_changes(num_changes));
}
/**
* Get the bounding box of this changeset.
*
* @returns Bounding box. Can be empty.
*/
osmium::Box& bounds() noexcept {
return m_bounds;
}
/**
* Get the bounding box of this changeset.
*
* @returns Bounding box. Can be empty.
*/
const osmium::Box& bounds() const noexcept {
return m_bounds;
}
@ -244,33 +243,29 @@ namespace osmium {
return reinterpret_cast<const char*>(data() + sizeof(Changeset));
}
/// Get the list of tags.
TagList& tags() {
return subitem_of_type<TagList>();
}
/// Get the list of tags.
const TagList& tags() const {
return subitem_of_type<const TagList>();
return osmium::detail::subitem_of_type<const TagList>(cbegin(), cend());
}
/**
* Set named attribute.
*
* @param attr Name of the attribute (must be one of "id", "version", "changeset", "timestamp", "uid", "visible")
* @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);
set_id(value);
} else if (!strcmp(attr, "num_changes")) {
num_changes(value);
set_num_changes(value);
} else if (!strcmp(attr, "created_at")) {
created_at(osmium::Timestamp(value));
set_created_at(osmium::Timestamp(value));
} else if (!strcmp(attr, "closed_at")) {
closed_at(osmium::Timestamp(value));
set_closed_at(osmium::Timestamp(value));
} else if (!strcmp(attr, "uid")) {
uid(value);
set_uid(value);
}
}
@ -303,7 +298,8 @@ namespace osmium {
}; // class Changeset
static_assert(sizeof(Changeset) % osmium::memory::align_bytes == 0, "Class osmium::Changeset has wrong size to be aligned properly!");
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.

View File

@ -1,156 +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 <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/osm/item_type.hpp>
#include <osmium/osm/object.hpp>
#include <osmium/osm/timestamp.hpp>
#include <osmium/osm/types.hpp>
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 T>
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<const T*>(m_prev);
}
const T& curr() const {
return *static_cast<const T*>(m_curr);
}
const T& next() const {
return *static_cast<const T*>(m_next);
}
}; // class DiffObjectDerived
typedef DiffObjectDerived<osmium::Node> DiffNode;
typedef DiffObjectDerived<osmium::Way> DiffWay;
typedef DiffObjectDerived<osmium::Relation> DiffRelation;
} // namespace osmium
#endif // OSMIUM_OSM_DIFF_OBJECT_HPP
#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 <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/osm/item_type.hpp>
#include <osmium/osm/object.hpp>
#include <osmium/osm/timestamp.hpp>
#include <osmium/osm/types.hpp>
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() noexcept :
m_prev(nullptr),
m_curr(nullptr),
m_next(nullptr) {
}
explicit DiffObject(osmium::OSMObject& prev, osmium::OSMObject& curr, osmium::OSMObject& next) noexcept :
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 noexcept {
return *m_prev;
}
const osmium::OSMObject& curr() const noexcept {
return *m_curr;
}
const osmium::OSMObject& next() const noexcept {
return *m_next;
}
bool first() const noexcept {
return m_prev == m_curr;
}
bool last() const noexcept {
return m_curr == m_next;
}
osmium::item_type type() const noexcept {
return m_curr->type();
}
osmium::object_id_type id() const noexcept {
return m_curr->id();
}
osmium::object_version_type version() const noexcept {
return m_curr->version();
}
osmium::changeset_id_type changeset() const noexcept {
return m_curr->changeset();
}
const osmium::Timestamp start_time() const noexcept {
return m_curr->timestamp();
}
const osmium::Timestamp end_time() const noexcept {
return last() ? osmium::Timestamp() : m_next->timestamp();
}
}; // class DiffObject
template <class T>
class DiffObjectDerived : public DiffObject {
public:
DiffObjectDerived(T& prev, T& curr, T& next) noexcept :
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 noexcept {
return *static_cast<const T*>(m_prev);
}
const T& curr() const noexcept {
return *static_cast<const T*>(m_curr);
}
const T& next() const noexcept {
return *static_cast<const T*>(m_next);
}
}; // class DiffObjectDerived
typedef DiffObjectDerived<osmium::Node> DiffNode;
typedef DiffObjectDerived<osmium::Way> DiffWay;
typedef DiffObjectDerived<osmium::Relation> DiffRelation;
} // namespace osmium
#endif // OSMIUM_OSM_DIFF_OBJECT_HPP

View File

@ -1,55 +1,74 @@
#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 <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/memory/item.hpp>
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
#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 <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/memory/item.hpp>
namespace osmium {
namespace detail {
template <class TSubitem, class TIter>
inline TSubitem& subitem_of_type(TIter it, TIter end) {
for (; it != end; ++it) {
if (it->type() == TSubitem::itemtype) {
return reinterpret_cast<TSubitem&>(*it);
}
}
// If no subitem of the TSubitem type was found,
// return a default constructed one.
static TSubitem subitem;
return subitem;
}
} // namespace detail
/**
* \brief OSMEntity is the abstract base class for the OSMObject and
* Changeset classes.
*/
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

View File

@ -68,20 +68,20 @@ namespace osmium {
}; // enum type
inline type operator|(const type lhs, const type rhs) {
inline type operator|(const type lhs, const type rhs) noexcept {
return static_cast<type>(static_cast<int>(lhs) | static_cast<int> (rhs));
}
inline type& operator|=(type& lhs, const type rhs) {
inline type& operator|=(type& lhs, const type rhs) noexcept {
lhs = lhs | rhs;
return lhs;
}
inline type operator&(const type lhs, const type rhs) {
inline type operator&(const type lhs, const type rhs) noexcept {
return static_cast<type>(static_cast<int>(lhs) & static_cast<int> (rhs));
}
inline type operator&=(type& lhs, const type rhs) {
inline type operator&=(type& lhs, const type rhs) noexcept {
lhs = lhs & rhs;
return lhs;
}

View File

@ -56,7 +56,7 @@ namespace osmium {
}; // enum class item_type
inline item_type char_to_item_type(const char c) {
inline item_type char_to_item_type(const char c) noexcept {
switch (c) {
case 'X':
return item_type::undefined;
@ -87,7 +87,10 @@ namespace osmium {
}
}
inline char item_type_to_char(const item_type type) {
// avoid g++ false positive
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type"
inline char item_type_to_char(const item_type type) noexcept {
switch (type) {
case item_type::undefined:
return 'X';
@ -116,7 +119,7 @@ namespace osmium {
}
}
inline const char* item_type_to_name(const item_type type) {
inline const char* item_type_to_name(const item_type type) noexcept {
switch (type) {
case item_type::undefined:
return "undefined";
@ -144,12 +147,19 @@ namespace osmium {
return "inner_ring";
}
}
#pragma GCC diagnostic pop
template <typename TChar, typename TTraits>
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const item_type item_type) {
return out << item_type_to_char(item_type);
}
/**
* This exception is thrown when a visitor encounters an unknown item type.
* Under usual circumstance this should not happen. If it does happen, it
* probably means the buffer contains different kinds of objects than were
* expected or that there is some kind of data corruption.
*/
struct unknown_type : public std::runtime_error {
unknown_type() :

View File

@ -33,19 +33,16 @@ DEALINGS IN THE SOFTWARE.
*/
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <iosfwd>
#include <limits>
#include <stdexcept>
#include <string>
#include <iostream>
#include <osmium/util/compatibility.hpp>
#include <osmium/util/double.hpp>
namespace osmium {
@ -86,7 +83,7 @@ namespace osmium {
public:
/// this value is used for a coordinate to mark it as undefined
// this value is used for a coordinate to mark it as undefined
// MSVC doesn't declare std::numeric_limits<int32_t>::max() as
// constexpr, so we hard code this for the time being.
// static constexpr int32_t undefined_coordinate = std::numeric_limits<int32_t>::max();
@ -105,7 +102,7 @@ namespace osmium {
/**
* Create undefined Location.
*/
explicit constexpr Location() :
explicit constexpr Location() noexcept :
m_x(undefined_coordinate),
m_y(undefined_coordinate) {
}
@ -115,7 +112,7 @@ namespace osmium {
* Note that these coordinates are coordinate_precision
* times larger than the real coordinates.
*/
constexpr Location(const int32_t x, const int32_t y) :
constexpr Location(const int32_t x, const int32_t y) noexcept :
m_x(x),
m_y(y) {
}
@ -125,7 +122,7 @@ namespace osmium {
* Note that these coordinates are coordinate_precision
* times larger than the real coordinates.
*/
constexpr Location(const int64_t x, const int64_t y) :
constexpr Location(const int64_t x, const int64_t y) noexcept :
m_x(static_cast<int32_t>(x)),
m_y(static_cast<int32_t>(y)) {
}
@ -171,12 +168,12 @@ namespace osmium {
return m_y;
}
Location& x(const int32_t x) noexcept {
Location& set_x(const int32_t x) noexcept {
m_x = x;
return *this;
}
Location& y(const int32_t y) noexcept {
Location& set_y(const int32_t y) noexcept {
m_y = y;
return *this;
}
@ -219,44 +216,21 @@ namespace osmium {
return fix_to_double(m_y);
}
Location& lon(double lon) noexcept {
Location& set_lon(double lon) noexcept {
m_x = double_to_fix(lon);
return *this;
}
Location& lat(double lat) noexcept {
Location& set_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 <typename T>
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 <typename T>
T as_string(T iterator, const char separator) const {
iterator = coordinate2string(iterator, lon());
iterator = osmium::util::double2string(iterator, lon(), 7);
*iterator++ = separator;
return coordinate2string(iterator, lat());
return osmium::util::double2string(iterator, lat(), 7);
}
}; // class Location
@ -268,7 +242,7 @@ namespace osmium {
return lhs.x() == rhs.x() && lhs.y() == rhs.y();
}
inline OSMIUM_CONSTEXPR bool operator!=(const Location& lhs, const Location& rhs) {
inline OSMIUM_CONSTEXPR bool operator!=(const Location& lhs, const Location& rhs) noexcept {
return ! (lhs == rhs);
}
@ -281,15 +255,15 @@ namespace osmium {
return (lhs.x() == rhs.x() && lhs.y() < rhs.y()) || lhs.x() < rhs.x();
}
inline OSMIUM_CONSTEXPR bool operator>(const Location& lhs, const Location& rhs) {
inline OSMIUM_CONSTEXPR bool operator>(const Location& lhs, const Location& rhs) noexcept {
return rhs < lhs;
}
inline OSMIUM_CONSTEXPR bool operator<=(const Location& lhs, const Location& rhs) {
inline OSMIUM_CONSTEXPR bool operator<=(const Location& lhs, const Location& rhs) noexcept {
return ! (rhs < lhs);
}
inline OSMIUM_CONSTEXPR bool operator>=(const Location& lhs, const Location& rhs) {
inline OSMIUM_CONSTEXPR bool operator>=(const Location& lhs, const Location& rhs) noexcept {
return ! (lhs < rhs);
}

View File

@ -58,15 +58,11 @@ namespace osmium {
static constexpr osmium::item_type itemtype = osmium::item_type::node;
const osmium::Location location() const {
osmium::Location location() const noexcept {
return m_location;
}
osmium::Location& location() {
return m_location;
}
Node& location(const osmium::Location& location) {
Node& set_location(const osmium::Location& location) {
m_location = location;
return *this;
}

View File

@ -54,20 +54,27 @@ namespace osmium {
public:
NodeRef(const osmium::object_id_type ref=0, const osmium::Location& location=Location()) :
NodeRef(const osmium::object_id_type ref=0, const osmium::Location& location=Location()) noexcept :
m_ref(ref),
m_location(location) {
}
osmium::object_id_type ref() const {
osmium::object_id_type ref() const noexcept {
return m_ref;
}
osmium::unsigned_object_id_type positive_ref() const {
osmium::unsigned_object_id_type positive_ref() const noexcept {
return static_cast<osmium::unsigned_object_id_type>(std::abs(m_ref));
}
osmium::Location location() const {
/**
* Get reference to location in this NodeRef. Can be used to update it.
*/
osmium::Location& location() noexcept {
return m_location;
}
osmium::Location location() const noexcept {
return m_location;
}
@ -79,33 +86,47 @@ namespace osmium {
return m_location.lat();
}
void location(const osmium::Location& location) {
int32_t x() const noexcept {
return m_location.x();
}
int32_t y() const noexcept {
return m_location.y();
}
NodeRef& set_ref(const osmium::object_id_type ref) noexcept {
m_ref = ref;
return *this;
}
NodeRef& set_location(const osmium::Location& location) noexcept {
m_location = location;
return *this;
}
}; // class NodeRef
inline bool operator==(const NodeRef& lhs, const NodeRef& rhs) {
inline bool operator==(const NodeRef& lhs, const NodeRef& rhs) noexcept {
return lhs.ref() == rhs.ref();
}
inline bool operator!=(const NodeRef& lhs, const NodeRef& rhs) {
inline bool operator!=(const NodeRef& lhs, const NodeRef& rhs) noexcept {
return ! (lhs == rhs);
}
inline bool operator<(const NodeRef& lhs, const NodeRef& rhs) {
inline bool operator<(const NodeRef& lhs, const NodeRef& rhs) noexcept {
return lhs.ref() < rhs.ref();
}
inline bool operator>(const NodeRef& lhs, const NodeRef& rhs) {
inline bool operator>(const NodeRef& lhs, const NodeRef& rhs) noexcept {
return rhs < lhs;
}
inline bool operator<=(const NodeRef& lhs, const NodeRef& rhs) {
inline bool operator<=(const NodeRef& lhs, const NodeRef& rhs) noexcept {
return ! (rhs < lhs);
}
inline bool operator>=(const NodeRef& lhs, const NodeRef& rhs) {
inline bool operator>=(const NodeRef& lhs, const NodeRef& rhs) noexcept {
return ! (lhs < rhs);
}
@ -122,7 +143,7 @@ namespace osmium {
*/
struct location_equal {
bool operator()(const NodeRef& lhs, const NodeRef& rhs) const {
bool operator()(const NodeRef& lhs, const NodeRef& rhs) const noexcept {
return lhs.location() == rhs.location();
}
@ -137,7 +158,7 @@ namespace osmium {
*/
struct location_less {
bool operator()(const NodeRef& lhs, const NodeRef& rhs) const {
bool operator()(const NodeRef& lhs, const NodeRef& rhs) const noexcept {
return lhs.location() < rhs.location();
}

View File

@ -1,135 +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 <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 <iterator>
#include <osmium/memory/item.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/node_ref.hpp>
namespace osmium {
/**
* A vector of NodeRef objects. Usually this is not instatiated directly,
* but one of its subclasses are used.
*/
template <osmium::item_type TItemType>
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 NodeRef*> 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
#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 <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 <iterator>
#include <osmium/memory/item.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/node_ref.hpp>
namespace osmium {
/**
* A vector of NodeRef objects. Usually this is not instatiated directly,
* but one of its subclasses are used.
*/
template <osmium::item_type TItemType>
class NodeRefList : public osmium::memory::Item {
public:
static constexpr osmium::item_type itemtype = TItemType;
NodeRefList() noexcept :
osmium::memory::Item(sizeof(NodeRefList), TItemType) {
}
bool empty() const noexcept {
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 = &*(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 NodeRef*> 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(cend());
}
const_reverse_iterator crend() const {
return const_reverse_iterator(cbegin());
}
}; // class NodeRefList
} // namespace osmium
#endif // OSMIUM_OSM_NODE_REF_LIST_HPP

View File

@ -41,6 +41,7 @@ DEALINGS IN THE SOFTWARE.
#include <osmium/memory/collection.hpp>
#include <osmium/memory/item.hpp>
#include <osmium/memory/item_iterator.hpp>
#include <osmium/osm/entity.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/location.hpp>
@ -62,19 +63,19 @@ namespace osmium {
user_id_type m_uid;
changeset_id_type m_changeset;
size_t sizeof_object() const {
size_t sizeof_object() const noexcept {
return sizeof(OSMObject) + (type() == item_type::node ? sizeof(osmium::Location) : 0) + sizeof(string_size_type);
}
unsigned char* user_position() {
unsigned char* user_position() noexcept {
return data() + sizeof_object() - sizeof(string_size_type);
}
const unsigned char* user_position() const {
const unsigned char* user_position() const noexcept {
return data() + sizeof_object() - sizeof(string_size_type);
}
string_size_type user_size() const {
string_size_type user_size() const noexcept {
return *reinterpret_cast<const string_size_type*>(user_position());
}
@ -98,52 +99,28 @@ namespace osmium {
m_changeset(0) {
}
void user_size(string_size_type size) {
void set_user_size(string_size_type size) {
*reinterpret_cast<string_size_type*>(user_position()) = size;
}
template <class T>
T& subitem_of_type() {
for (iterator it = begin(); it != end(); ++it) {
if (it->type() == T::itemtype) {
return reinterpret_cast<T&>(*it);
}
}
static T subitem;
return subitem;
}
template <class T>
const T& subitem_of_type() const {
for (const_iterator it = cbegin(); it != cend(); ++it) {
if (it->type() == T::itemtype) {
return reinterpret_cast<const T&>(*it);
}
}
static const T subitem;
return subitem;
}
public:
/// Get ID of this object.
object_id_type id() const {
object_id_type id() const noexcept {
return m_id;
}
/// Get absolute value of the ID of this object.
unsigned_object_id_type positive_id() const {
unsigned_object_id_type positive_id() const noexcept {
return static_cast<unsigned_object_id_type>(std::abs(m_id));
}
/**
* Set ID of this object.
*
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& id(object_id_type id) {
OSMObject& set_id(object_id_type id) noexcept {
m_id = id;
return *this;
}
@ -151,28 +128,28 @@ namespace osmium {
/**
* Set ID of this object.
*
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& id(const char* id) {
return this->id(osmium::string_to_object_id(id));
OSMObject& set_id(const char* id) {
return set_id(osmium::string_to_object_id(id));
}
/// Is this object marked as deleted?
bool deleted() const {
bool deleted() const noexcept {
return m_deleted;
}
/// Is this object marked visible (ie not deleted)?
bool visible() const {
bool visible() const noexcept {
return !deleted();
}
/**
* Mark this object as deleted (or not).
*
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& deleted(bool deleted) {
OSMObject& set_deleted(bool deleted) noexcept {
m_deleted = deleted;
return *this;
}
@ -180,9 +157,9 @@ namespace osmium {
/**
* Mark this object as visible (ie not deleted) (or not).
*
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& visible(bool visible) {
OSMObject& set_visible(bool visible) noexcept {
m_deleted = !visible;
return *this;
}
@ -191,13 +168,13 @@ namespace osmium {
* Mark this object as visible (ie not deleted) or deleted.
*
* @param visible Either "true" or "false"
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& visible(const char* visible) {
OSMObject& set_visible(const char* visible) {
if (!strcmp("true", visible)) {
this->visible(true);
set_visible(true);
} else if (!strcmp("false", visible)) {
this->visible(false);
set_visible(false);
} else {
throw std::invalid_argument("Unknown value for visible attribute (allowed is 'true' or 'false')");
}
@ -205,16 +182,16 @@ namespace osmium {
}
/// Get version of this object.
object_version_type version() const {
object_version_type version() const noexcept {
return m_version;
}
/**
* Set object version.
*
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& version(object_version_type version) {
OSMObject& set_version(object_version_type version) noexcept {
m_version = version;
return *this;
}
@ -222,23 +199,23 @@ namespace osmium {
/**
* Set object version.
*
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& version(const char* version) {
return this->version(string_to_object_version(version));
OSMObject& set_version(const char* version) {
return set_version(string_to_object_version(version));
}
/// Get changeset id of this object.
changeset_id_type changeset() const {
changeset_id_type changeset() const noexcept {
return m_changeset;
}
/**
* Set changeset id of this object.
*
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& changeset(changeset_id_type changeset) {
OSMObject& set_changeset(changeset_id_type changeset) noexcept {
m_changeset = changeset;
return *this;
}
@ -246,23 +223,23 @@ namespace osmium {
/**
* Set changeset id of this object.
*
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& changeset(const char* changeset) {
return this->changeset(string_to_changeset_id(changeset));
OSMObject& set_changeset(const char* changeset) {
return set_changeset(string_to_changeset_id(changeset));
}
/// Get user id of this object.
user_id_type uid() const {
user_id_type uid() const noexcept {
return m_uid;
}
/**
* Set user id of this object.
*
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& uid(user_id_type uid) {
OSMObject& set_uid(user_id_type uid) noexcept {
m_uid = uid;
return *this;
}
@ -271,9 +248,9 @@ namespace osmium {
* 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.
* @returns Reference to object to make calls chainable.
*/
OSMObject& uid_from_signed(signed_user_id_type uid) {
OSMObject& set_uid_from_signed(signed_user_id_type uid) noexcept {
m_uid = uid < 0 ? 0 : static_cast<user_id_type>(uid);
return *this;
}
@ -281,19 +258,19 @@ namespace osmium {
/**
* Set user id of this object.
*
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& uid(const char* uid) {
return this->uid_from_signed(string_to_user_id(uid));
OSMObject& set_uid(const char* uid) {
return set_uid_from_signed(string_to_user_id(uid));
}
/// Is this user anonymous?
bool user_is_anonymous() const {
bool user_is_anonymous() const noexcept {
return m_uid == 0;
}
/// Get timestamp when this object last changed.
osmium::Timestamp timestamp() const {
osmium::Timestamp timestamp() const noexcept {
return m_timestamp;
}
@ -301,26 +278,21 @@ namespace osmium {
* Set the timestamp when this object last changed.
*
* @param timestamp Timestamp
* @return Reference to object to make calls chainable.
* @returns Reference to object to make calls chainable.
*/
OSMObject& timestamp(const osmium::Timestamp timestamp) {
OSMObject& set_timestamp(const osmium::Timestamp timestamp) noexcept {
m_timestamp = timestamp;
return *this;
}
/// Get user name for this object.
const char* user() const {
const char* user() const noexcept {
return reinterpret_cast<const char*>(data() + sizeof_object());
}
/// Get the list of tags for this object.
TagList& tags() {
return subitem_of_type<TagList>();
}
/// Get the list of tags for this object.
const TagList& tags() const {
return subitem_of_type<const TagList>();
return osmium::detail::subitem_of_type<const TagList>(cbegin(), cend());
}
/**
@ -341,17 +313,17 @@ namespace osmium {
*/
void set_attribute(const char* attr, const char* value) {
if (!strcmp(attr, "id")) {
id(value);
set_id(value);
} else if (!strcmp(attr, "version")) {
version(value);
set_version(value);
} else if (!strcmp(attr, "changeset")) {
changeset(value);
set_changeset(value);
} else if (!strcmp(attr, "timestamp")) {
timestamp(osmium::Timestamp(value));
set_timestamp(osmium::Timestamp(value));
} else if (!strcmp(attr, "uid")) {
uid(value);
set_uid(value);
} else if (!strcmp(attr, "visible")) {
visible(value);
set_visible(value);
}
}
@ -363,7 +335,7 @@ namespace osmium {
}
iterator end() {
return iterator(data() + padded_size());
return iterator(next());
}
const_iterator cbegin() const {
@ -371,7 +343,7 @@ namespace osmium {
}
const_iterator cend() const {
return const_iterator(data() + padded_size());
return const_iterator(next());
}
const_iterator begin() const {
@ -382,6 +354,42 @@ namespace osmium {
return cend();
}
template <class T>
using t_iterator = osmium::memory::ItemIterator<T>;
template <class T>
using t_const_iterator = osmium::memory::ItemIterator<const T>;
template <class T>
t_iterator<T> begin() {
return t_iterator<T>(subitems_position(), next());
}
template <class T>
t_iterator<T> end() {
return t_iterator<T>(next(), next());
}
template <class T>
t_const_iterator<T> cbegin() const {
return t_const_iterator<T>(subitems_position(), next());
}
template <class T>
t_const_iterator<T> cend() const {
return t_const_iterator<T>(next(), next());
}
template <class T>
t_const_iterator<T> begin() const {
return cbegin<T>();
}
template <class T>
t_const_iterator<T> end() const {
return cend<T>();
}
}; // class OSMObject
static_assert(sizeof(OSMObject) % osmium::memory::align_bytes == 0, "Class osmium::OSMObject has wrong size to be aligned properly!");
@ -389,13 +397,13 @@ namespace osmium {
/**
* OSMObjects are equal if their type, id, and version are equal.
*/
inline bool operator==(const OSMObject& lhs, const OSMObject& rhs) {
inline bool operator==(const OSMObject& lhs, const OSMObject& rhs) noexcept {
return lhs.type() == rhs.type() &&
lhs.id() == rhs.id() &&
lhs.version() == rhs.version();
}
inline bool operator!=(const OSMObject& lhs, const OSMObject& rhs) {
inline bool operator!=(const OSMObject& lhs, const OSMObject& rhs) noexcept {
return ! (lhs == rhs);
}
@ -404,7 +412,7 @@ namespace osmium {
* 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) {
inline bool operator<(const OSMObject& lhs, const OSMObject& rhs) noexcept {
if (lhs.type() != rhs.type()) {
return lhs.type() < rhs.type();
}
@ -412,15 +420,15 @@ namespace osmium {
lhs.positive_id() < rhs.positive_id();
}
inline bool operator>(const OSMObject& lhs, const OSMObject& rhs) {
inline bool operator>(const OSMObject& lhs, const OSMObject& rhs) noexcept {
return rhs < lhs;
}
inline bool operator<=(const OSMObject& lhs, const OSMObject& rhs) {
inline bool operator<=(const OSMObject& lhs, const OSMObject& rhs) noexcept {
return ! (rhs < lhs);
}
inline bool operator>=(const OSMObject& lhs, const OSMObject& rhs) {
inline bool operator>=(const OSMObject& lhs, const OSMObject& rhs) noexcept {
return ! (lhs < rhs);
}

View File

@ -1,110 +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 <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/osm/object.hpp>
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
#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 <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/osm/object.hpp>
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 noexcept {
return lhs == rhs;
}
bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const noexcept {
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 noexcept {
return lhs.type() == rhs.type() &&
lhs.id() == rhs.id();
}
bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const noexcept {
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 noexcept {
return lhs < rhs;
}
bool operator()(const osmium::OSMObject* lhs, const osmium::OSMObject* rhs) const noexcept {
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 noexcept {
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 noexcept {
return operator()(*lhs, *rhs);
}
}; // struct object_order_type_id_reverse_version
} // namespace osmium
#endif // OSMIUM_OSM_OBJECT_COMPARISONS_HPP

View File

@ -93,7 +93,7 @@ namespace osmium {
}
}
void set_role_size(string_size_type size) {
void set_role_size(string_size_type size) noexcept {
m_role_size = size;
}
@ -101,34 +101,34 @@ namespace osmium {
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) :
RelationMember(const object_id_type ref=0, const item_type type=item_type(), const bool full=false) noexcept :
m_ref(ref),
m_type(type),
m_flags(full ? 1 : 0) {
}
object_id_type ref() const {
object_id_type ref() const noexcept {
return m_ref;
}
RelationMember& ref(object_id_type ref) {
RelationMember& ref(object_id_type ref) noexcept {
m_ref = ref;
return *this;
}
unsigned_object_id_type positive_ref() const {
unsigned_object_id_type positive_ref() const noexcept {
return static_cast<unsigned_object_id_type>(std::abs(m_ref));
}
item_type type() const {
item_type type() const noexcept {
return m_type;
}
bool full_member() const {
bool full_member() const noexcept {
return m_flags == 1;
}
const char* role() const {
const char* role() const noexcept {
return reinterpret_cast<const char*>(data() + sizeof(RelationMember));
}
@ -164,7 +164,7 @@ namespace osmium {
friend class osmium::builder::ObjectBuilder<osmium::Relation>;
Relation() :
Relation() noexcept :
OSMObject(sizeof(Relation), osmium::item_type::relation) {
}
@ -173,11 +173,11 @@ namespace osmium {
static constexpr osmium::item_type itemtype = osmium::item_type::relation;
RelationMemberList& members() {
return subitem_of_type<RelationMemberList>();
return osmium::detail::subitem_of_type<RelationMemberList>(begin(), end());
}
const RelationMemberList& members() const {
return subitem_of_type<const RelationMemberList>();
return osmium::detail::subitem_of_type<const RelationMemberList>(cbegin(), cend());
}
}; // class Relation

View File

@ -51,7 +51,7 @@ namespace osmium {
public:
explicit constexpr Segment(const osmium::Location& location1, const osmium::Location& location2) :
explicit constexpr Segment(const osmium::Location& location1, const osmium::Location& location2) noexcept :
m_first(location1),
m_second(location2) {
}
@ -65,12 +65,12 @@ namespace osmium {
~Segment() = default;
/// Return first Location of Segment.
OSMIUM_CONSTEXPR osmium::Location first() const {
OSMIUM_CONSTEXPR osmium::Location first() const noexcept {
return m_first;
}
/// Return second Location of Segment.
OSMIUM_CONSTEXPR osmium::Location second() const {
OSMIUM_CONSTEXPR osmium::Location second() const noexcept {
return m_second;
}
@ -84,11 +84,11 @@ namespace osmium {
}; // class Segment
/// Segments are equal if both their locations are equal
inline OSMIUM_CONSTEXPR bool operator==(const Segment& lhs, const Segment& rhs) {
inline OSMIUM_CONSTEXPR bool operator==(const Segment& lhs, const Segment& rhs) noexcept {
return lhs.first() == rhs.first() && lhs.second() == rhs.second();
}
inline OSMIUM_CONSTEXPR bool operator!=(const Segment& lhs, const Segment& rhs) {
inline OSMIUM_CONSTEXPR bool operator!=(const Segment& lhs, const Segment& rhs) noexcept {
return ! (lhs == rhs);
}

View File

@ -76,7 +76,7 @@ namespace osmium {
static constexpr item_type collection_type = item_type::tag_list;
const char* key() const {
const char* key() const noexcept {
return reinterpret_cast<const char*>(data());
}

View File

@ -67,13 +67,13 @@ namespace osmium {
public:
constexpr Timestamp() :
constexpr Timestamp() noexcept :
m_timestamp(0) {
}
// Not "explicit" so that conversions from time_t work
// like in node.timestamp(123);
constexpr Timestamp(time_t timestamp) :
constexpr Timestamp(time_t timestamp) noexcept :
m_timestamp(static_cast<uint32_t>(timestamp)) {
}
@ -82,7 +82,7 @@ namespace osmium {
* Throws std::invalid_argument, if the timestamp can not be parsed.
*/
explicit Timestamp(const char* timestamp) {
#ifndef WIN32
#ifndef _WIN32
struct tm tm {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
@ -105,14 +105,24 @@ namespace osmium {
#endif
}
constexpr time_t seconds_since_epoch() const {
constexpr time_t seconds_since_epoch() const noexcept {
return static_cast<time_t>(m_timestamp);
}
constexpr operator time_t() const {
constexpr operator time_t() const noexcept {
return static_cast<time_t>(m_timestamp);
}
template <typename T>
void operator+=(T time_difference) noexcept {
m_timestamp += time_difference;
}
template <typename T>
void operator-=(T time_difference) noexcept {
m_timestamp -= time_difference;
}
/**
* Return UTC Unix time as string in ISO date/time format.
*/
@ -140,11 +150,11 @@ namespace osmium {
}; // class Timestamp
inline OSMIUM_CONSTEXPR Timestamp start_of_time() {
inline OSMIUM_CONSTEXPR Timestamp start_of_time() noexcept {
return Timestamp(1);
}
inline OSMIUM_CONSTEXPR Timestamp end_of_time() {
inline OSMIUM_CONSTEXPR Timestamp end_of_time() noexcept {
return Timestamp(std::numeric_limits<time_t>::max());
}

View File

@ -71,19 +71,19 @@ namespace osmium {
* 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) {
inline bool operator<(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept {
return (lhs.first() == rhs.first() && lhs.second() < rhs.second()) || lhs.first() < rhs.first();
}
inline bool operator>(const UndirectedSegment& lhs, const UndirectedSegment& rhs) {
inline bool operator>(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept {
return rhs < lhs;
}
inline bool operator<=(const UndirectedSegment& lhs, const UndirectedSegment& rhs) {
inline bool operator<=(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept {
return ! (rhs < lhs);
}
inline bool operator>=(const UndirectedSegment& lhs, const UndirectedSegment& rhs) {
inline bool operator>=(const UndirectedSegment& lhs, const UndirectedSegment& rhs) noexcept {
return ! (lhs < rhs);
}

View File

@ -1,115 +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 <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/memory/item.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/object.hpp>
#include <osmium/osm/types.hpp>
#include <osmium/osm/node_ref.hpp>
#include <osmium/osm/node_ref_list.hpp>
namespace osmium {
namespace builder {
template <class T> class ObjectBuilder;
}
/**
* List of node references (id and location) in a way.
*/
class WayNodeList : public NodeRefList<osmium::item_type::way_node_list> {
public:
WayNodeList():
NodeRefList<osmium::item_type::way_node_list>() {
}
}; // 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<osmium::Way>;
Way() :
OSMObject(sizeof(Way), osmium::item_type::way) {
}
public:
WayNodeList& nodes() {
return subitem_of_type<WayNodeList>();
}
const WayNodeList& nodes() const {
return subitem_of_type<const WayNodeList>();
}
/**
* 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
#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 <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/memory/item.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/object.hpp>
#include <osmium/osm/types.hpp>
#include <osmium/osm/node_ref.hpp>
#include <osmium/osm/node_ref_list.hpp>
namespace osmium {
namespace builder {
template <class T> class ObjectBuilder;
}
/**
* List of node references (id and location) in a way.
*/
class WayNodeList : public NodeRefList<osmium::item_type::way_node_list> {
public:
WayNodeList():
NodeRefList<osmium::item_type::way_node_list>() {
}
}; // 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<osmium::Way>;
Way() noexcept :
OSMObject(sizeof(Way), osmium::item_type::way) {
}
public:
WayNodeList& nodes() {
return osmium::detail::subitem_of_type<WayNodeList>(begin(), end());
}
const WayNodeList& nodes() const {
return osmium::detail::subitem_of_type<const WayNodeList>(cbegin(), cend());
}
/**
* 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.set_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

File diff suppressed because it is too large Load Diff

View File

@ -1,131 +1,158 @@
#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 <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 <cstddef>
#include <iosfwd>
#include <osmium/osm/types.hpp>
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 <typename TChar, typename TTraits>
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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
#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 <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 <algorithm>
#include <cstddef>
#include <iosfwd>
#include <iterator>
#include <osmium/osm/types.hpp>
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 };
bool m_removed = false;
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) noexcept :
m_member_id(member_id),
m_relation_pos(relation_pos),
m_member_pos(member_pos) {
}
osmium::object_id_type member_id() const noexcept {
return m_member_id;
}
size_t relation_pos() const noexcept {
return m_relation_pos;
}
size_t member_pos() const noexcept {
return m_member_pos;
}
size_t buffer_offset() const noexcept {
return m_buffer_offset;
}
void set_buffer_offset(size_t offset) noexcept {
m_buffer_offset = offset;
}
bool removed() const noexcept {
return m_removed;
}
void remove() noexcept {
m_removed = true;
}
}; // 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) noexcept {
return a.member_id() < b.member_id();
}
template <typename TChar, typename TTraits>
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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;
}
/**
* Count the number of MemberMeta objects in the iterator range
* that are not marked as removed.
*
* @tparam TIter Iterator that dereferences to a MemberMeta
* @param begin Begin of iterator range
* @param end End of iterator range
*/
template <class TIter>
inline typename std::iterator_traits<TIter>::difference_type count_not_removed(TIter begin, TIter end) {
return std::count_if(begin, end, [](MemberMeta& mm) {
return !mm.removed();
});
}
} // namespace relations
} // namespace osmium
#endif // OSMIUM_RELATIONS_DETAIL_MEMBER_META_HPP

View File

@ -1,136 +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 <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 <iosfwd>
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 <typename TChar, typename TTraits>
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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
#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 <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 <iosfwd>
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() noexcept :
m_relation_offset(0) {
}
explicit RelationMeta(size_t relation_offset) noexcept :
m_relation_offset(relation_offset) {
}
/**
* Get offset of relation in buffer.
*/
size_t relation_offset() const noexcept {
return m_relation_offset;
}
/**
* Increment the m_need_members counter.
*/
void increment_need_members() noexcept {
++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 noexcept {
return m_need_members == 0;
}
}; // class RelationMeta
template <typename TChar, typename TTraits>
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& 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;
/**
* @returns 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

View File

@ -51,27 +51,27 @@ namespace osmium {
bool operator()(const TKey& rule_key, const char* tag_key) {
return rule_key == tag_key;
}
};
}; // struct match_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;
}
};
}; // struct match_key_prefix
template <class TValue>
struct match_value {
bool operator()(const TValue& rule_value, const char* tag_value) {
return rule_value == tag_value;
}
};
}; // struct match_value
template <>
struct match_value<void> {
bool operator()(const bool, const char*) {
return true;
}
};
}; // struct match_value<void>
template <class TKey, class TValue=void, class TKeyComp=match_key<TKey>, class TValueComp=match_value<TValue>>
class Filter {
@ -99,7 +99,7 @@ namespace osmium {
result(r) {
}
};
}; // struct Rule
std::vector<Rule> m_rules;
bool m_default_result;
@ -135,7 +135,7 @@ namespace osmium {
return m_default_result;
}
}; // Filter
}; // class Filter
typedef Filter<std::string, std::string> KeyValueFilter;
typedef Filter<std::string> KeyFilter;

View File

@ -1,58 +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 <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 <regex>
#include <string>
#include <osmium/tags/filter.hpp>
namespace osmium {
namespace tags {
template <>
struct match_value<std::regex> {
bool operator()(const std::regex& rule_value, const char* tag_value) {
return std::regex_match(tag_value, rule_value);
}
};
typedef Filter<std::string, std::regex> RegexFilter;
} // namespace tags
} // namespace osmium
#endif // OSMIUM_TAGS_REGEX_FILTER_HPP
#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 <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 <regex>
#include <string>
#include <osmium/tags/filter.hpp>
namespace osmium {
namespace tags {
template <>
struct match_value<std::regex> {
bool operator()(const std::regex& rule_value, const char* tag_value) {
return std::regex_match(tag_value, rule_value);
}
}; // struct match_value<std::regex>
typedef Filter<std::string, std::regex> RegexFilter;
} // namespace tags
} // namespace osmium
#endif // OSMIUM_TAGS_REGEX_FILTER_HPP

View File

@ -1,104 +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 <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 <algorithm>
#include <memory>
namespace osmium {
namespace thread {
class function_wrapper {
struct impl_base {
virtual void call() = 0;
virtual ~impl_base() {
}
};
std::unique_ptr<impl_base> impl;
template <typename F>
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 <typename F>
function_wrapper(F&& f) :
impl(new impl_type<F>(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<bool>(impl);
}
}; // class function_wrapper
} // namespace thread
} // namespace osmium
#endif // OSMIUM_THREAD_FUNCTION_WRAPPER_HPP
#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 <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 <algorithm>
#include <memory>
namespace osmium {
namespace thread {
class function_wrapper {
struct impl_base {
virtual void call() = 0;
virtual ~impl_base() {
}
}; // struct impl_base
std::unique_ptr<impl_base> impl;
template <typename F>
struct impl_type : impl_base {
F m_functor;
impl_type(F&& functor) :
m_functor(std::move(functor)) {
}
void call() {
m_functor();
}
}; // struct impl_type
public:
// Constructor must not be "explicit" for wrapper
// to work seemlessly.
template <typename F>
function_wrapper(F&& f) :
impl(new impl_type<F>(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<bool>(impl);
}
}; // class function_wrapper
} // namespace thread
} // namespace osmium
#endif // OSMIUM_THREAD_FUNCTION_WRAPPER_HPP

View File

@ -1,180 +1,204 @@
#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 <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 <algorithm>
#include <atomic>
#include <cstddef>
#include <cstdlib>
#include <future>
#include <thread>
#include <type_traits>
#include <vector>
#include <osmium/thread/queue.hpp>
#include <osmium/thread/name.hpp>
#include <osmium/thread/function_wrapper.hpp>
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<std::thread>& m_threads;
public:
explicit thread_joiner(std::vector<std::thread>& threads) :
m_threads(threads) {
}
~thread_joiner() {
for (auto& thread : m_threads) {
if (thread.joinable()) {
thread.join();
}
}
}
}; // class thread_joiner
std::atomic<bool> m_done;
osmium::thread::Queue<function_wrapper> m_work_queue;
std::vector<std::thread> 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<int>(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 <typename TFunction>
std::future<typename std::result_of<TFunction()>::type> submit(TFunction f) {
typedef typename std::result_of<TFunction()>::type result_type;
std::packaged_task<result_type()> task(std::move(f));
std::future<result_type> 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
#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 <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 <algorithm>
#include <atomic>
#include <cstddef>
#include <cstdlib>
#include <future>
#include <thread>
#include <type_traits>
#include <vector>
#include <osmium/thread/queue.hpp>
#include <osmium/thread/name.hpp>
#include <osmium/thread/function_wrapper.hpp>
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<std::thread>& m_threads;
public:
explicit thread_joiner(std::vector<std::thread>& threads) :
m_threads(threads) {
}
~thread_joiner() {
for (auto& thread : m_threads) {
if (thread.joinable()) {
thread.join();
}
}
}
}; // class thread_joiner
std::atomic<bool> m_done;
osmium::thread::Queue<function_wrapper> m_work_queue;
std::vector<std::thread> 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<int>(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 <typename TFunction>
std::future<typename std::result_of<TFunction()>::type> submit(TFunction f) {
typedef typename std::result_of<TFunction()>::type result_type;
std::packaged_task<result_type()> task(std::move(f));
std::future<result_type> future_result(task.get_future());
m_work_queue.push(std::move(task));
return future_result;
}
}; // class Pool
/**
* Wrapper for classes that can't be copied but need to be copyable for
* putting them in the pool.
*/
template <class TWrapped>
class SharedPtrWrapper {
std::shared_ptr<TWrapped> m_task;
public:
typedef typename std::result_of<TWrapped()>::type result_type;
template <typename... TArgs>
SharedPtrWrapper(TArgs&&... args) :
m_task(std::make_shared<TWrapped>(std::forward<TArgs>(args)...)) {
}
result_type operator()() {
return m_task->operator()();
}
}; // class SharedPtrWrapper
} // namespace thread
} // namespace osmium
#endif // OSMIUM_THREAD_POOL_HPP

View File

@ -1,5 +1,5 @@
#ifndef OSMIUM_CONFIG_CONSTEXPR_HPP
#define OSMIUM_CONFIG_CONSTEXPR_HPP
#ifndef OSMIUM_UTIL_COMPATIBILITY_HPP
#define OSMIUM_UTIL_COMPATIBILITY_HPP
/*
@ -44,4 +44,4 @@ DEALINGS IN THE SOFTWARE.
# define OSMIUM_NORETURN [[noreturn]]
#endif
#endif // OSMIUM_CONFIG_CONSTEXPR_HPP
#endif // OSMIUM_UTIL_COMPATIBILITY_HPP

View File

@ -87,7 +87,7 @@ namespace osmium {
public:
explicit VerboseOutput(bool verbose=false) :
explicit VerboseOutput(bool verbose=false) noexcept :
m_start(time(NULL)),
m_verbose(verbose),
m_newline(true) {