Merge commit 'babbda98a6ea1d53a8bc5015ef5dfb313c47186a' into libosmium-2.10.0
This commit is contained in:
+37
-27
@@ -617,7 +617,7 @@ namespace osmium {
|
||||
|
||||
template <typename TBuilder, typename... TArgs>
|
||||
inline void add_user(TBuilder& builder, const TArgs&... args) {
|
||||
builder.add_user(get_user(args...));
|
||||
builder.set_user(get_user(args...));
|
||||
}
|
||||
|
||||
// ==============================================================
|
||||
@@ -761,11 +761,13 @@ namespace osmium {
|
||||
static_assert(sizeof...(args) > 0, "add_node() must have buffer and at least one additional argument");
|
||||
static_assert(detail::are_all_handled_by<detail::any_node_handlers, TArgs...>::value, "Attribute not allowed in add_node()");
|
||||
|
||||
NodeBuilder builder(buffer);
|
||||
{
|
||||
NodeBuilder builder(buffer);
|
||||
|
||||
detail::add_basic<detail::node_handler>(builder, args...);
|
||||
detail::add_user(builder, args...);
|
||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||
detail::add_basic<detail::node_handler>(builder, args...);
|
||||
detail::add_user(builder, args...);
|
||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||
}
|
||||
|
||||
return buffer.commit();
|
||||
}
|
||||
@@ -782,12 +784,14 @@ namespace osmium {
|
||||
static_assert(sizeof...(args) > 0, "add_way() must have buffer and at least one additional argument");
|
||||
static_assert(detail::are_all_handled_by<detail::any_way_handlers, TArgs...>::value, "Attribute not allowed in add_way()");
|
||||
|
||||
WayBuilder builder(buffer);
|
||||
{
|
||||
WayBuilder builder(buffer);
|
||||
|
||||
detail::add_basic<detail::object_handler>(builder, args...);
|
||||
detail::add_user(builder, args...);
|
||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||
detail::add_list<WayNodeListBuilder, detail::nodes_handler>(builder, args...);
|
||||
detail::add_basic<detail::object_handler>(builder, args...);
|
||||
detail::add_user(builder, args...);
|
||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||
detail::add_list<WayNodeListBuilder, detail::nodes_handler>(builder, args...);
|
||||
}
|
||||
|
||||
return buffer.commit();
|
||||
}
|
||||
@@ -804,12 +808,14 @@ namespace osmium {
|
||||
static_assert(sizeof...(args) > 0, "add_relation() must have buffer and at least one additional argument");
|
||||
static_assert(detail::are_all_handled_by<detail::any_relation_handlers, TArgs...>::value, "Attribute not allowed in add_relation()");
|
||||
|
||||
RelationBuilder builder(buffer);
|
||||
{
|
||||
RelationBuilder builder(buffer);
|
||||
|
||||
detail::add_basic<detail::object_handler>(builder, args...);
|
||||
detail::add_user(builder, args...);
|
||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||
detail::add_list<RelationMemberListBuilder, detail::members_handler>(builder, args...);
|
||||
detail::add_basic<detail::object_handler>(builder, args...);
|
||||
detail::add_user(builder, args...);
|
||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||
detail::add_list<RelationMemberListBuilder, detail::members_handler>(builder, args...);
|
||||
}
|
||||
|
||||
return buffer.commit();
|
||||
}
|
||||
@@ -826,12 +832,14 @@ namespace osmium {
|
||||
static_assert(sizeof...(args) > 0, "add_changeset() must have buffer and at least one additional argument");
|
||||
static_assert(detail::are_all_handled_by<detail::any_changeset_handlers, TArgs...>::value, "Attribute not allowed in add_changeset()");
|
||||
|
||||
ChangesetBuilder builder(buffer);
|
||||
{
|
||||
ChangesetBuilder builder(buffer);
|
||||
|
||||
detail::add_basic<detail::changeset_handler>(builder, args...);
|
||||
detail::add_user(builder, args...);
|
||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||
detail::add_list<ChangesetDiscussionBuilder, detail::discussion_handler>(builder, args...);
|
||||
detail::add_basic<detail::changeset_handler>(builder, args...);
|
||||
detail::add_user(builder, args...);
|
||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||
detail::add_list<ChangesetDiscussionBuilder, detail::discussion_handler>(builder, args...);
|
||||
}
|
||||
|
||||
return buffer.commit();
|
||||
}
|
||||
@@ -848,15 +856,17 @@ namespace osmium {
|
||||
static_assert(sizeof...(args) > 0, "add_area() must have buffer and at least one additional argument");
|
||||
static_assert(detail::are_all_handled_by<detail::any_area_handlers, TArgs...>::value, "Attribute not allowed in add_area()");
|
||||
|
||||
AreaBuilder builder(buffer);
|
||||
{
|
||||
AreaBuilder builder(buffer);
|
||||
|
||||
detail::add_basic<detail::object_handler>(builder, args...);
|
||||
detail::add_user(builder, args...);
|
||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||
detail::add_basic<detail::object_handler>(builder, args...);
|
||||
detail::add_user(builder, args...);
|
||||
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||
|
||||
(void)std::initializer_list<int>{
|
||||
(detail::ring_handler::set_value(builder, args), 0)...
|
||||
};
|
||||
(void)std::initializer_list<int>{
|
||||
(detail::ring_handler::set_value(builder, args), 0)...
|
||||
};
|
||||
}
|
||||
|
||||
return buffer.commit();
|
||||
}
|
||||
|
||||
+45
-60
@@ -45,6 +45,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/memory/item.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
@@ -53,6 +54,10 @@ namespace osmium {
|
||||
*/
|
||||
namespace builder {
|
||||
|
||||
/**
|
||||
* Parent class for individual builder classes. Instantiate one of
|
||||
* its derived classes.
|
||||
*/
|
||||
class Builder {
|
||||
|
||||
osmium::memory::Buffer& m_buffer;
|
||||
@@ -71,20 +76,34 @@ namespace osmium {
|
||||
m_buffer(buffer),
|
||||
m_parent(parent),
|
||||
m_item_offset(buffer.written()) {
|
||||
m_buffer.reserve_space(size);
|
||||
reserve_space(size);
|
||||
assert(buffer.is_aligned());
|
||||
if (m_parent) {
|
||||
assert(m_buffer.builder_count() == 1 && "Only one sub-builder can be open at any time.");
|
||||
m_parent->add_size(size);
|
||||
} else {
|
||||
assert(m_buffer.builder_count() == 0 && "Only one builder can be open at any time.");
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
m_buffer.increment_builder_count();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
~Builder() = default;
|
||||
#else
|
||||
~Builder() noexcept {
|
||||
m_buffer.decrement_builder_count();
|
||||
}
|
||||
#endif
|
||||
|
||||
osmium::memory::Item& item() const {
|
||||
return *reinterpret_cast<osmium::memory::Item*>(m_buffer.data() + m_item_offset);
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned char* reserve_space(size_t size) {
|
||||
return m_buffer.reserve_space(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add padding to buffer (if needed) to align data properly.
|
||||
@@ -102,7 +121,7 @@ namespace osmium {
|
||||
void add_padding(bool self = false) {
|
||||
const auto padding = osmium::memory::align_bytes - (size() % osmium::memory::align_bytes);
|
||||
if (padding != osmium::memory::align_bytes) {
|
||||
std::fill_n(m_buffer.reserve_space(padding), padding, 0);
|
||||
std::fill_n(reserve_space(padding), padding, 0);
|
||||
if (self) {
|
||||
add_size(padding);
|
||||
} else if (m_parent) {
|
||||
@@ -123,12 +142,6 @@ namespace osmium {
|
||||
return item().byte_size();
|
||||
}
|
||||
|
||||
void add_item(const osmium::memory::Item* item) {
|
||||
unsigned char* target = m_buffer.reserve_space(item->padded_size());
|
||||
std::copy_n(reinterpret_cast<const unsigned char*>(item), item->padded_size(), target);
|
||||
add_size(item->padded_size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserve space for an object of class T in buffer and return
|
||||
* pointer to it.
|
||||
@@ -136,7 +149,7 @@ namespace osmium {
|
||||
template <typename T>
|
||||
T* reserve_space_for() {
|
||||
assert(m_buffer.is_aligned());
|
||||
return reinterpret_cast<T*>(m_buffer.reserve_space(sizeof(T)));
|
||||
return reinterpret_cast<T*>(reserve_space(sizeof(T)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,7 +162,7 @@ namespace osmium {
|
||||
* @returns The number of bytes appended (length).
|
||||
*/
|
||||
osmium::memory::item_size_type append(const char* data, const osmium::memory::item_size_type length) {
|
||||
unsigned char* target = m_buffer.reserve_space(length);
|
||||
unsigned char* target = reserve_space(length);
|
||||
std::copy_n(reinterpret_cast<const unsigned char*>(data), length, target);
|
||||
return length;
|
||||
}
|
||||
@@ -170,65 +183,37 @@ namespace osmium {
|
||||
* @returns The number of bytes appended (always 1).
|
||||
*/
|
||||
osmium::memory::item_size_type append_zero() {
|
||||
*m_buffer.reserve_space(1) = '\0';
|
||||
*reserve_space(1) = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// Return the buffer this builder is using.
|
||||
osmium::memory::Buffer& buffer() noexcept {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subitem to the object being built. This can be something
|
||||
* like a TagList or RelationMemberList.
|
||||
*/
|
||||
void add_item(const osmium::memory::Item& item) {
|
||||
m_buffer.add_item(item);
|
||||
add_size(item.padded_size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the version of add_item() taking a
|
||||
* reference instead.
|
||||
*/
|
||||
OSMIUM_DEPRECATED void add_item(const osmium::memory::Item* item) {
|
||||
assert(item);
|
||||
add_item(*item);
|
||||
}
|
||||
|
||||
}; // class Builder
|
||||
|
||||
template <typename 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 (without \0 termination).
|
||||
*/
|
||||
void add_user(const char* user, const string_size_type length) {
|
||||
object().set_user_size(length + 1);
|
||||
add_size(append(user, length) + append_zero());
|
||||
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)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()));
|
||||
}
|
||||
|
||||
}; // class ObjectBuilder
|
||||
|
||||
} // namespace builder
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
+279
-35
@@ -45,6 +45,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/builder/builder.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/tag.hpp>
|
||||
@@ -55,6 +56,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/timestamp.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
@@ -66,12 +68,18 @@ namespace osmium {
|
||||
|
||||
namespace builder {
|
||||
|
||||
class TagListBuilder : public ObjectBuilder<TagList> {
|
||||
class TagListBuilder : public Builder {
|
||||
|
||||
public:
|
||||
|
||||
explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
ObjectBuilder<TagList>(buffer, parent) {
|
||||
Builder(buffer, parent, sizeof(TagList)) {
|
||||
new (&item()) TagList();
|
||||
}
|
||||
|
||||
explicit TagListBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(TagList)) {
|
||||
new (&item()) TagList();
|
||||
}
|
||||
|
||||
~TagListBuilder() {
|
||||
@@ -169,21 +177,27 @@ namespace osmium {
|
||||
}; // class TagListBuilder
|
||||
|
||||
template <typename T>
|
||||
class NodeRefListBuilder : public ObjectBuilder<T> {
|
||||
class NodeRefListBuilder : public Builder {
|
||||
|
||||
public:
|
||||
|
||||
explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
ObjectBuilder<T>(buffer, parent) {
|
||||
Builder(buffer, parent, sizeof(T)) {
|
||||
new (&item()) T();
|
||||
}
|
||||
|
||||
explicit NodeRefListBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(T)) {
|
||||
new (&item()) T();
|
||||
}
|
||||
|
||||
~NodeRefListBuilder() {
|
||||
static_cast<Builder*>(this)->add_padding();
|
||||
add_padding();
|
||||
}
|
||||
|
||||
void add_node_ref(const NodeRef& node_ref) {
|
||||
new (static_cast<Builder*>(this)->reserve_space_for<osmium::NodeRef>()) osmium::NodeRef(node_ref);
|
||||
static_cast<Builder*>(this)->add_size(sizeof(osmium::NodeRef));
|
||||
new (reserve_space_for<osmium::NodeRef>()) osmium::NodeRef(node_ref);
|
||||
add_size(sizeof(osmium::NodeRef));
|
||||
}
|
||||
|
||||
void add_node_ref(const object_id_type ref, const osmium::Location& location = Location{}) {
|
||||
@@ -196,7 +210,7 @@ namespace osmium {
|
||||
using OuterRingBuilder = NodeRefListBuilder<OuterRing>;
|
||||
using InnerRingBuilder = NodeRefListBuilder<InnerRing>;
|
||||
|
||||
class RelationMemberListBuilder : public ObjectBuilder<RelationMemberList> {
|
||||
class RelationMemberListBuilder : public Builder {
|
||||
|
||||
/**
|
||||
* Add role to buffer.
|
||||
@@ -219,7 +233,13 @@ namespace osmium {
|
||||
public:
|
||||
|
||||
explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
ObjectBuilder<RelationMemberList>(buffer, parent) {
|
||||
Builder(buffer, parent, sizeof(RelationMemberList)) {
|
||||
new (&item()) RelationMemberList();
|
||||
}
|
||||
|
||||
explicit RelationMemberListBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(RelationMemberList)) {
|
||||
new (&item()) RelationMemberList();
|
||||
}
|
||||
|
||||
~RelationMemberListBuilder() {
|
||||
@@ -245,7 +265,7 @@ namespace osmium {
|
||||
add_size(sizeof(RelationMember));
|
||||
add_role(*member, role, role_length);
|
||||
if (full_member) {
|
||||
add_item(full_member);
|
||||
add_item(*full_member);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +301,7 @@ namespace osmium {
|
||||
|
||||
}; // class RelationMemberListBuilder
|
||||
|
||||
class ChangesetDiscussionBuilder : public ObjectBuilder<ChangesetDiscussion> {
|
||||
class ChangesetDiscussionBuilder : public Builder {
|
||||
|
||||
osmium::ChangesetComment* m_comment = nullptr;
|
||||
|
||||
@@ -309,7 +329,13 @@ namespace osmium {
|
||||
public:
|
||||
|
||||
explicit ChangesetDiscussionBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
ObjectBuilder<ChangesetDiscussion>(buffer, parent) {
|
||||
Builder(buffer, parent, sizeof(ChangesetDiscussion)) {
|
||||
new (&item()) ChangesetDiscussion();
|
||||
}
|
||||
|
||||
explicit ChangesetDiscussionBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(ChangesetDiscussion)) {
|
||||
new (&item()) ChangesetDiscussion();
|
||||
}
|
||||
|
||||
~ChangesetDiscussionBuilder() {
|
||||
@@ -339,19 +365,101 @@ namespace osmium {
|
||||
|
||||
}; // class ChangesetDiscussionBuilder
|
||||
|
||||
template <typename T>
|
||||
class OSMObjectBuilder : public ObjectBuilder<T> {
|
||||
#define OSMIUM_FORWARD(setter) \
|
||||
template <typename... TArgs> \
|
||||
type& setter(TArgs&&... args) { \
|
||||
object().setter(std::forward<TArgs>(args)...); \
|
||||
return static_cast<type&>(*this); \
|
||||
}
|
||||
|
||||
template <typename TDerived, typename T>
|
||||
class OSMObjectBuilder : public Builder {
|
||||
|
||||
using type = TDerived;
|
||||
|
||||
constexpr static const size_t min_size_for_user = osmium::memory::padded_length(sizeof(string_size_type) + 1);
|
||||
|
||||
public:
|
||||
|
||||
explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
ObjectBuilder<T>(buffer, parent) {
|
||||
static_cast<Builder*>(this)->reserve_space_for<string_size_type>();
|
||||
static_cast<Builder*>(this)->add_size(sizeof(string_size_type));
|
||||
Builder(buffer, parent, sizeof(T) + min_size_for_user) {
|
||||
new (&item()) T();
|
||||
add_size(min_size_for_user);
|
||||
std::fill_n(object().data() + sizeof(T), min_size_for_user, 0);
|
||||
object().set_user_size(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the object buing built.
|
||||
*
|
||||
* Note that this reference will be invalidated by every action
|
||||
* on the builder that might make the buffer grow. This includes
|
||||
* calls to set_user() and any time a new sub-builder is created.
|
||||
*/
|
||||
T& object() noexcept {
|
||||
return static_cast<T&>(item());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user Pointer to user name.
|
||||
* @param length Length of user name (without \0 termination).
|
||||
*/
|
||||
TDerived& set_user(const char* user, const string_size_type length) {
|
||||
const auto size_of_object = sizeof(T) + sizeof(string_size_type);
|
||||
assert(object().user_size() == 1 && (size() <= size_of_object + osmium::memory::padded_length(1))
|
||||
&& "set_user() must be called at most once and before any sub-builders");
|
||||
const auto available_space = min_size_for_user - sizeof(string_size_type) - 1;
|
||||
if (length > available_space) {
|
||||
const auto space_needed = osmium::memory::padded_length(length - available_space);
|
||||
reserve_space(space_needed);
|
||||
add_size(static_cast<uint32_t>(space_needed));
|
||||
}
|
||||
std::copy_n(user, length, object().data() + size_of_object);
|
||||
std::fill_n(object().data() + size_of_object + length, osmium::memory::padded_length(length + 1) - length, 0);
|
||||
object().set_user_size(length + 1);
|
||||
|
||||
return static_cast<TDerived&>(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user Pointer to \0-terminated user name.
|
||||
*/
|
||||
TDerived& set_user(const char* user) {
|
||||
return set_user(user, static_cast_with_assert<string_size_type>(std::strlen(user)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user User name.
|
||||
*/
|
||||
TDerived& set_user(const std::string& user) {
|
||||
return set_user(user.data(), static_cast_with_assert<string_size_type>(user.size()));
|
||||
}
|
||||
|
||||
/// @deprecated Use set_user(...) instead.
|
||||
template <typename... TArgs>
|
||||
OSMIUM_DEPRECATED void add_user(TArgs&&... args) {
|
||||
set_user(std::forward<TArgs>(args)...);
|
||||
}
|
||||
|
||||
OSMIUM_FORWARD(set_id)
|
||||
OSMIUM_FORWARD(set_visible)
|
||||
OSMIUM_FORWARD(set_deleted)
|
||||
OSMIUM_FORWARD(set_version)
|
||||
OSMIUM_FORWARD(set_changeset)
|
||||
OSMIUM_FORWARD(set_uid)
|
||||
OSMIUM_FORWARD(set_uid_from_signed)
|
||||
OSMIUM_FORWARD(set_timestamp)
|
||||
OSMIUM_FORWARD(set_attribute)
|
||||
OSMIUM_FORWARD(set_removed)
|
||||
|
||||
void add_tags(const std::initializer_list<std::pair<const char*, const char*>>& tags) {
|
||||
osmium::builder::TagListBuilder tl_builder(static_cast<Builder*>(this)->buffer(), this);
|
||||
osmium::builder::TagListBuilder tl_builder{buffer(), this};
|
||||
for (const auto& p : tags) {
|
||||
tl_builder.add_tag(p.first, p.second);
|
||||
}
|
||||
@@ -359,19 +467,40 @@ namespace osmium {
|
||||
|
||||
}; // class OSMObjectBuilder
|
||||
|
||||
using NodeBuilder = OSMObjectBuilder<osmium::Node>;
|
||||
using RelationBuilder = OSMObjectBuilder<osmium::Relation>;
|
||||
class NodeBuilder : public OSMObjectBuilder<NodeBuilder, Node> {
|
||||
|
||||
class WayBuilder : public OSMObjectBuilder<osmium::Way> {
|
||||
using type = NodeBuilder;
|
||||
|
||||
public:
|
||||
|
||||
explicit NodeBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
OSMObjectBuilder<NodeBuilder, Node>(buffer, parent) {
|
||||
}
|
||||
|
||||
explicit NodeBuilder(Builder& parent) :
|
||||
OSMObjectBuilder<NodeBuilder, Node>(parent.buffer(), &parent) {
|
||||
}
|
||||
|
||||
OSMIUM_FORWARD(set_location)
|
||||
|
||||
}; // class NodeBuilder
|
||||
|
||||
class WayBuilder : public OSMObjectBuilder<WayBuilder, Way> {
|
||||
|
||||
using type = WayBuilder;
|
||||
|
||||
public:
|
||||
|
||||
explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
OSMObjectBuilder<osmium::Way>(buffer, parent) {
|
||||
OSMObjectBuilder<WayBuilder, Way>(buffer, parent) {
|
||||
}
|
||||
|
||||
explicit WayBuilder(Builder& parent) :
|
||||
OSMObjectBuilder<WayBuilder, Way>(parent.buffer(), &parent) {
|
||||
}
|
||||
|
||||
void add_node_refs(const std::initializer_list<osmium::NodeRef>& nodes) {
|
||||
osmium::builder::WayNodeListBuilder builder(buffer(), this);
|
||||
osmium::builder::WayNodeListBuilder builder{buffer(), this};
|
||||
for (const auto& node_ref : nodes) {
|
||||
builder.add_node_ref(node_ref);
|
||||
}
|
||||
@@ -379,32 +508,147 @@ namespace osmium {
|
||||
|
||||
}; // class WayBuilder
|
||||
|
||||
class AreaBuilder : public OSMObjectBuilder<osmium::Area> {
|
||||
class RelationBuilder : public OSMObjectBuilder<RelationBuilder, Relation> {
|
||||
|
||||
using type = RelationBuilder;
|
||||
|
||||
public:
|
||||
|
||||
explicit RelationBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
OSMObjectBuilder<RelationBuilder, Relation>(buffer, parent) {
|
||||
}
|
||||
|
||||
explicit RelationBuilder(Builder& parent) :
|
||||
OSMObjectBuilder<RelationBuilder, Relation>(parent.buffer(), &parent) {
|
||||
}
|
||||
|
||||
}; // class RelationBuilder
|
||||
|
||||
class AreaBuilder : public OSMObjectBuilder<AreaBuilder, Area> {
|
||||
|
||||
using type = AreaBuilder;
|
||||
|
||||
public:
|
||||
|
||||
explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
OSMObjectBuilder<osmium::Area>(buffer, parent) {
|
||||
OSMObjectBuilder<AreaBuilder, Area>(buffer, parent) {
|
||||
}
|
||||
|
||||
explicit AreaBuilder(Builder& parent) :
|
||||
OSMObjectBuilder<AreaBuilder, Area>(parent.buffer(), &parent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize area attributes from the attributes of the given object.
|
||||
*/
|
||||
void initialize_from_object(const osmium::OSMObject& source) {
|
||||
osmium::Area& area = object();
|
||||
area.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());
|
||||
set_id(osmium::object_id_to_area_id(source.id(), source.type()));
|
||||
set_version(source.version());
|
||||
set_changeset(source.changeset());
|
||||
set_timestamp(source.timestamp());
|
||||
set_visible(source.visible());
|
||||
set_uid(source.uid());
|
||||
set_user(source.user());
|
||||
}
|
||||
|
||||
}; // class AreaBuilder
|
||||
|
||||
using ChangesetBuilder = ObjectBuilder<osmium::Changeset>;
|
||||
class ChangesetBuilder : public Builder {
|
||||
|
||||
using type = ChangesetBuilder;
|
||||
|
||||
constexpr static const size_t min_size_for_user = osmium::memory::padded_length(1);
|
||||
|
||||
public:
|
||||
|
||||
explicit ChangesetBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(Changeset) + min_size_for_user) {
|
||||
new (&item()) Changeset();
|
||||
add_size(min_size_for_user);
|
||||
std::fill_n(object().data() + sizeof(Changeset), min_size_for_user, 0);
|
||||
object().set_user_size(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the changeset buing built.
|
||||
*
|
||||
* Note that this reference will be invalidated by every action
|
||||
* on the builder that might make the buffer grow. This includes
|
||||
* calls to set_user() and any time a new sub-builder is created.
|
||||
*/
|
||||
Changeset& object() noexcept {
|
||||
return static_cast<Changeset&>(item());
|
||||
}
|
||||
|
||||
OSMIUM_FORWARD(set_id)
|
||||
OSMIUM_FORWARD(set_uid)
|
||||
OSMIUM_FORWARD(set_uid_from_signed)
|
||||
OSMIUM_FORWARD(set_created_at)
|
||||
OSMIUM_FORWARD(set_closed_at)
|
||||
OSMIUM_FORWARD(set_num_changes)
|
||||
OSMIUM_FORWARD(set_num_comments)
|
||||
OSMIUM_FORWARD(set_attribute)
|
||||
OSMIUM_FORWARD(set_removed)
|
||||
|
||||
// @deprecated Use set_bounds() instead.
|
||||
OSMIUM_DEPRECATED osmium::Box& bounds() noexcept {
|
||||
return object().bounds();
|
||||
}
|
||||
|
||||
ChangesetBuilder& set_bounds(const osmium::Box& box) noexcept {
|
||||
object().bounds() = box;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user Pointer to user name.
|
||||
* @param length Length of user name (without \0 termination).
|
||||
*/
|
||||
ChangesetBuilder& set_user(const char* user, const string_size_type length) {
|
||||
assert(object().user_size() == 1 && (size() <= sizeof(Changeset) + osmium::memory::padded_length(1))
|
||||
&& "set_user() must be called at most once and before any sub-builders");
|
||||
const auto available_space = min_size_for_user - 1;
|
||||
if (length > available_space) {
|
||||
const auto space_needed = osmium::memory::padded_length(length - available_space);
|
||||
reserve_space(space_needed);
|
||||
add_size(static_cast<uint32_t>(space_needed));
|
||||
}
|
||||
std::copy_n(user, length, object().data() + sizeof(Changeset));
|
||||
std::fill_n(object().data() + sizeof(Changeset) + length, osmium::memory::padded_length(length + 1) - length, 0);
|
||||
object().set_user_size(length + 1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user Pointer to \0-terminated user name.
|
||||
*/
|
||||
ChangesetBuilder& set_user(const char* user) {
|
||||
return set_user(user, static_cast_with_assert<string_size_type>(std::strlen(user)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user User name.
|
||||
*/
|
||||
ChangesetBuilder& set_user(const std::string& user) {
|
||||
return set_user(user.data(), static_cast_with_assert<string_size_type>(user.size()));
|
||||
}
|
||||
|
||||
/// @deprecated Use set_user(...) instead.
|
||||
template <typename... TArgs>
|
||||
OSMIUM_DEPRECATED void add_user(TArgs&&... args) {
|
||||
set_user(std::forward<TArgs>(args)...);
|
||||
}
|
||||
|
||||
}; // class ChangesetBuilder
|
||||
|
||||
#undef OSMIUM_FORWARD
|
||||
|
||||
} // namespace builder
|
||||
|
||||
|
||||
Reference in New Issue
Block a user