1 #ifndef OSMIUM_OSM_RELATION_HPP
2 #define OSMIUM_OSM_RELATION_HPP
3 
4 /*
5 
6 This file is part of Osmium (https://osmcode.org/libosmium).
7 
8 Copyright 2013-2021 Jochen Topf <jochen@topf.org> and others (see README).
9 
10 Boost Software License - Version 1.0 - August 17th, 2003
11 
12 Permission is hereby granted, free of charge, to any person or organization
13 obtaining a copy of the software and accompanying documentation covered by
14 this license (the "Software") to use, reproduce, display, distribute,
15 execute, and transmit the Software, and to prepare derivative works of the
16 Software, and to permit third-parties to whom the Software is furnished to
17 do so, all subject to the following:
18 
19 The copyright notices in the Software and this entire statement, including
20 the above license grant, this restriction and the following disclaimer,
21 must be included in all copies of the Software, in whole or in part, and
22 all derivative works of the Software, unless such copies or derivative
23 works are solely in the form of machine-executable object code generated by
24 a source language processor.
25 
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
29 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
30 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
31 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32 DEALINGS IN THE SOFTWARE.
33 
34 */
35 
36 #include <osmium/memory/collection.hpp> // IWYU pragma: keep
37 #include <osmium/memory/item.hpp>
38 #include <osmium/osm/entity.hpp>
39 #include <osmium/osm/item_type.hpp>
40 #include <osmium/osm/object.hpp>
41 #include <osmium/osm/types.hpp>
42 #include <osmium/util/compatibility.hpp>
43 
44 #include <cstdint>
45 #include <cstdlib>
46 #include <iterator>
47 
48 namespace osmium {
49 
50     namespace builder {
51         template <typename TDerived, typename T>
52         class OSMObjectBuilder;
53 
54         class RelationMemberListBuilder;
55     } // namespace builder
56 
57     class RelationMember : public osmium::memory::detail::ItemHelper {
58 
59         friend class osmium::builder::RelationMemberListBuilder;
60 
61         object_id_type   m_ref;
62         item_type        m_type;
63         uint16_t         m_flags;
64         string_size_type m_role_size = 0;
65 
endpos()66         unsigned char* endpos() {
67             return data() + osmium::memory::padded_length(sizeof(RelationMember) + m_role_size);
68         }
69 
endpos() const70         const unsigned char* endpos() const {
71             return data() + osmium::memory::padded_length(sizeof(RelationMember) + m_role_size);
72         }
73 
74         template <typename TMember>
75         friend class osmium::memory::CollectionIterator;
76 
next()77         unsigned char* next() {
78             if (full_member()) {
79                 return endpos() + reinterpret_cast<osmium::memory::Item*>(endpos())->byte_size();
80             }
81             return endpos();
82         }
83 
next() const84         const unsigned char* next() const {
85             if (full_member()) {
86                 return endpos() + reinterpret_cast<const osmium::memory::Item*>(endpos())->byte_size();
87             }
88             return endpos();
89         }
90 
set_role_size(string_size_type size)91         void set_role_size(string_size_type size) noexcept {
92             m_role_size = size;
93         }
94 
95     public:
96 
97         static constexpr item_type collection_type = item_type::relation_member_list;
98 
RelationMember(const object_id_type ref=0,const item_type type=item_type (),const bool full=false)99         explicit RelationMember(const object_id_type ref = 0, const item_type type = item_type(), const bool full = false) noexcept :
100             m_ref(ref),
101             m_type(type),
102             m_flags(full ? 1 : 0) {
103         }
104 
105         RelationMember(const RelationMember&) = delete;
106         RelationMember& operator=(const RelationMember&) = delete;
107 
108         RelationMember(RelationMember&&) = delete;
109         RelationMember& operator=(RelationMember&&) = delete;
110 
111         ~RelationMember() noexcept = default;
112 
ref() const113         object_id_type ref() const noexcept {
114             return m_ref;
115         }
116 
117         /// @deprecated Use set_ref() instead.
ref(object_id_type ref)118         OSMIUM_DEPRECATED RelationMember& ref(object_id_type ref) noexcept {
119             m_ref = ref;
120             return *this;
121         }
122 
positive_ref() const123         unsigned_object_id_type positive_ref() const noexcept {
124             return static_cast<unsigned_object_id_type>(std::abs(m_ref));
125         }
126 
set_ref(const osmium::object_id_type ref)127         RelationMember& set_ref(const osmium::object_id_type ref) noexcept {
128             m_ref = ref;
129             return *this;
130         }
131 
type() const132         item_type type() const noexcept {
133             return m_type;
134         }
135 
full_member() const136         bool full_member() const noexcept {
137             return m_flags == 1;
138         }
139 
role() const140         const char* role() const noexcept {
141             return reinterpret_cast<const char*>(data() + sizeof(RelationMember));
142         }
143 
get_object()144         OSMObject& get_object() {
145             return *reinterpret_cast<OSMObject*>(endpos());
146         }
147 
get_object() const148         const OSMObject& get_object() const {
149             return *reinterpret_cast<const OSMObject*>(endpos());
150         }
151 
152     }; // class RelationMember
153 
154     class RelationMemberList : public osmium::memory::Collection<RelationMember, osmium::item_type::relation_member_list> {
155 
156     public:
157 
is_compatible_to(osmium::item_type t)158         constexpr static bool is_compatible_to(osmium::item_type t) noexcept {
159             return t == osmium::item_type::relation_member_list ||
160                    t == osmium::item_type::relation_member_list_with_full_members;
161         }
162 
163         RelationMemberList() noexcept = default;
164 
165     }; // class RelationMemberList
166 
167     static_assert(sizeof(RelationMemberList) % osmium::memory::align_bytes == 0, "Class osmium::RelationMemberList has wrong size to be aligned properly!");
168 
169     class Relation : public OSMObject {
170 
171         template <typename TDerived, typename T>
172         friend class osmium::builder::OSMObjectBuilder;
173 
Relation()174         Relation() noexcept :
175             OSMObject(sizeof(Relation), osmium::item_type::relation) {
176         }
177 
178     public:
179 
180         static constexpr osmium::item_type itemtype = osmium::item_type::relation;
181 
is_compatible_to(osmium::item_type t)182         constexpr static bool is_compatible_to(osmium::item_type t) noexcept {
183             return t == itemtype;
184         }
185 
186         /// Get a reference to the member list.
members()187         RelationMemberList& members() {
188             return osmium::detail::subitem_of_type<RelationMemberList>(begin(), end());
189         }
190 
191         /// Get a const reference to the member list.
members() const192         const RelationMemberList& members() const {
193             return osmium::detail::subitem_of_type<const RelationMemberList>(cbegin(), cend());
194         }
195 
196         /// Get a const reference to the member list.
cmembers() const197         const RelationMemberList& cmembers() const {
198             return osmium::detail::subitem_of_type<const RelationMemberList>(cbegin(), cend());
199         }
200 
201     }; // class Relation
202 
203     static_assert(sizeof(Relation) % osmium::memory::align_bytes == 0, "Class osmium::Relation has wrong size to be aligned properly!");
204 
205 } // namespace osmium
206 
207 #endif // OSMIUM_OSM_RELATION_HPP
208