AIS: explicit specification of copymove construction and assignment.
[marnav.git] / src / marnav / ais / message.hpp
blob5b7e8608c056da0195cbfeeb10f854aea3a78b20
1 #ifndef __AIS__MESSAGE__HPP__
2 #define __AIS__MESSAGE__HPP__
4 #include <memory>
5 #include <marnav/utils/bitset.hpp>
7 namespace marnav
9 namespace ais
12 /// All known AIS message IDs.
13 enum class message_id : uint8_t {
14 NONE = 0,
15 position_report_class_a = 1,
16 position_report_class_a_assigned_schedule = 2,
17 position_report_class_a_response_to_interrogation = 3,
18 base_station_report = 4,
19 static_and_voyage_related_data = 5,
20 binary_addressed_message = 6,
21 binary_acknowledge = 7,
22 binary_broadcast_message = 8,
23 standard_sar_aircraft_position_report = 9,
24 utc_and_date_inquiry = 10,
25 utc_and_date_response = 11,
26 addressed_safety_related_message = 12,
27 safety_related_acknowledgement_ = 13,
28 safety_related_broadcast_message = 14,
29 interrogation = 15,
30 assignment_mode_command = 16,
31 dgnss_binary_broadcast_message = 17,
32 standard_class_b_cs_position_report = 18,
33 extended_class_b_equipment_position_report = 19,
34 data_link_management = 20,
35 aid_to_navigation_report = 21,
36 channel_management = 22,
37 group_assignment_command = 23,
38 static_data_report = 24,
39 single_slot_binary_message = 25,
40 multiple_slot_binary_message_with_communications_state = 26,
41 position_report_for_long_range_applications = 27,
44 enum class navigation_status : uint8_t {
45 under_way_using_engine = 0,
46 at_anchor = 1,
47 not_under_command = 2,
48 restricted_maneuverability = 3,
49 constrained_by_her_draught = 4,
50 moored = 5,
51 aground = 6,
52 engaged_in_Fishing = 7,
53 under_way_sailing = 8,
54 reserved_09 = 9,
55 reserved_10 = 10,
56 reserved_11 = 11,
57 reserved_12 = 12,
58 reserved_13 = 13,
59 ais_sart_is_active = 14,
60 not_defined = 15, // default
63 enum class ship_type : uint8_t {
64 not_available = 0,
65 // 1..19 reserved for future use
66 wing_in_ground = 20,
67 wing_in_ground_hazardous_cat_a = 21,
68 wing_in_ground_hazardous_cat_b = 22,
69 wing_in_ground_hazardous_cat_c = 23,
70 wing_in_ground_hazardous_cat_d = 24,
71 // 25..29 WIG reserved for future use
72 fishing = 30,
73 towing = 31,
74 towing_large = 32, // exceeds 200m length or 25m breadth
75 dredging_or_underwater_ops = 33,
76 diving_ops = 34,
77 military_ops = 35,
78 sailing = 36,
79 pleasure_craft = 37,
80 // 38..39 reserved
81 high_speed_craft = 40,
82 high_speed_craft_hazardous_cat_a = 41,
83 high_speed_craft_hazardous_cat_b = 42,
84 high_speed_craft_hazardous_cat_c = 43,
85 high_speed_craft_hazardous_cat_d = 44,
86 // 45..48 HSC reserved for future use
87 high_speed_craft_no_info = 49,
88 pilot_vessel = 50,
89 search_and_rescue_vessel = 51,
90 tug = 52,
91 port_tender = 53,
92 anti_pollution_equipment = 54,
93 law_enforcement = 55,
94 // 56..57 spare, local vessel
95 medical_transport = 58,
96 noncombatant = 59,
97 passenger = 60,
98 passenger_hazardous_cat_a = 61,
99 passenger_hazardous_cat_b = 62,
100 passenger_hazardous_cat_c = 63,
101 passenger_hazardous_cat_d = 64,
102 // 65..68 Passenger reserved for future use
103 passenger_no_info = 69,
104 cargo = 70,
105 cargo_hazardous_cat_a = 71,
106 cargo_hazardous_cat_b = 72,
107 cargo_hazardous_cat_c = 73,
108 cargo_hazardous_cat_d = 74,
109 // 75..78 Cargo reserved for future use
110 cargo_no_info = 79,
111 tanker = 80,
112 tanker_hazardous_cat_a = 81,
113 tanker_hazardous_cat_b = 82,
114 tanker_hazardous_cat_c = 83,
115 tanker_hazardous_cat_d = 84,
116 // 85..88 Tanker reserved for future use
117 tanker_no_info = 89,
118 other = 90,
119 other_hazardous_cat_a = 91,
120 other_hazardous_cat_b = 92,
121 other_hazardous_cat_c = 93,
122 other_hazardous_cat_d = 94,
123 // 95..98 Other type reserved for future use
124 other_no_info = 99,
127 /// Electronic Position Fixing Device
128 enum class epfd_fix_type : uint8_t {
129 undefined = 0,
130 gps = 1,
131 glonass = 2,
132 combined_gps_glonass = 3,
133 loran_c = 4,
134 chayka = 5,
135 integrated_navigation_system = 6,
136 surveyed = 7,
137 galileo = 8,
140 enum class virtual_aid : uint32_t { real_aid = 0, virtual_aid = 1 };
142 enum class off_position_indicator : uint32_t { on_position = 0, off_position = 1 };
144 /// Enumeration of all aid types
145 enum class aid_type_id : uint32_t {
146 /// 0 : Default, Type of Aid to Navigation not specified
147 unspecified = 0,
149 /// 1 : Reference point
150 reference_point = 1,
152 /// 2 : RACON (radar transponder marking a navigation hazard)
153 racon = 2,
155 /// 3 : Fixed structure off shore, such as oil platforms, wind farms, rigs. (Note: This
156 /// code should identify an obstruction that is fitted with an Aid-to-Navigation AIS
157 /// station.)
158 fixed_structure = 3,
160 /// 4 : Spare, Reserved for future use.
161 reserved = 4,
163 /// 5 : Light, without sectors
164 light_no_sectors = 5,
166 /// 6 : Light, with sectors
167 light_sectors = 6,
169 /// 7 : Leading Light Front
170 leading_light_fromt = 7,
172 /// 8 : Leading Light Rear
173 leading_light_rear = 8,
175 /// 9 : Beacon, Cardinal N
176 beacon_cardinal_n = 9,
178 /// 10: Beacon, Cardinal E
179 beacon_cardinal_e = 10,
181 /// 11: Beacon, Cardinal S
182 beacon_cardinal_s = 11,
184 /// 12: Beacon, Cardinal W
185 beacon_cardinal_w = 12,
187 /// 13: Beacon, Port hand
188 beacon_port_hand = 13,
190 /// 14: Beacon, Starboard hand
191 beacon_starboard_hand = 14,
193 /// 15: Beacon, Preferred Channel port hand
194 beacon_preferred_channel_port_hand = 15,
196 ///< 16: Beacon, Preferred Channel starboard hand
197 beacon_preferred_channel_starboard_hand = 16,
199 /// 17: Beacon, Isolated danger
200 beacon_isolated_danger = 17,
202 /// 18: Beacon, Safe water
203 beacon_safe_water = 18,
205 /// 19: Beacon, Special mark
206 beacon_sepcial_mark = 19,
208 /// 20: Cardinal Mark N
209 cardinal_n = 20,
211 /// 21: Cardinal Mark E
212 cardinal_e = 21,
214 /// 22: Cardinal Mark S
215 cardinal_s = 22,
217 /// 23: Cardinal Mark W
218 cardinal_w = 23,
220 /// 24: Port hand Mark
221 mark_port_hand = 24,
223 /// 25: Starboard hand Mark
224 mark_starboard_hand = 25,
226 /// 26: Preferred Channel Port hand
227 preferred_channel_port_hand = 26,
229 /// 27: Preferred Channel Starboard hand
230 preferred_channel_starboard_hand = 27,
232 /// 28: Isolated danger
233 isolated_danger = 28,
235 /// 29: Safe Water
236 safe_water = 29,
238 /// 30: Special Mark
239 special_mark = 30,
241 /// 31: Light Vessel / LANBY / Rigs
242 light_vessel = 31,
246 enum class maneuver_indicator_id : uint32_t { not_available = 0, normal = 1, special = 2 };
248 // AIS data is coded in a binary form. This implies a need for special
249 // value that mark the invalidity of a certain value.
250 /// @{
252 /// Value for a longitude that is not specified.
253 constexpr static const uint32_t longitude_not_available = 0x6791AC0;
255 /// Value for a latitude that is not specified.
256 constexpr static const uint32_t latitude_not_available = 0x3412140;
258 /// Value for a longitude that is not specified, short version.
259 constexpr static const uint32_t longitude_not_available_short = 0x1a838;
261 /// Value for a latitude that is not specified, short version.
262 constexpr static const uint32_t latitude_not_available_short = 0xd548;
264 /// Value for a speed over ground that is not specified.
265 constexpr static const uint32_t sog_not_available = 1023;
267 /// Value for a course over ground that is not specified.
268 constexpr static const uint32_t cog_not_available = 3600;
270 /// Value for a heading that is not specified.
271 constexpr static const uint32_t hdg_not_available = 511;
273 /// Value for a rate of turn that is not specified.
274 constexpr static const int32_t rot_not_available = 128;
276 /// Value to indicate the absense of a timestamp.
277 constexpr static const uint8_t timestamp_not_available = 60;
279 /// Value for a year that is not specified.
280 constexpr static const uint32_t year_not_available = 0;
282 /// Value for a month that is not specified.
283 constexpr static const uint32_t month_not_available = 0;
285 /// Value for a day that is not specified.
286 constexpr static const uint32_t day_not_available = 0;
288 /// Value for a hour that is not specified.
289 constexpr static const uint32_t hour_not_available = 24;
291 /// Value for a minute that is not specified.
292 constexpr static const uint32_t minute_not_available = 60;
294 /// Value for a second that is not specified.
295 constexpr static const uint32_t second_not_available = 60;
297 /// @}
299 /// Type for raw AIS data.
300 using raw = utils::bitset<uint8_t>;
302 /// @{
304 char decode_sixbit_ascii(uint8_t value);
305 uint8_t encode_sixbit_ascii(char c);
307 /// @}
309 std::string trim_ais_string(const std::string & s);
311 /// @brief Base class for all AIS messages.
312 class message
314 friend std::vector<std::pair<std::string, uint32_t>> encode_message(const message & msg);
316 public:
317 virtual ~message() = default;
318 message() = delete;
319 message(const message &) = default;
320 message & operator=(const message &) = default;
321 message(message &&) = default;
322 message & operator=(message &&) = default;
324 message_id type() const { return message_type; }
326 protected:
327 /// Represents data to be read from / written to a bitset.
328 /// The offset and number of bits (or sixbits) is encoded in the
329 /// template signature.
331 /// This template is used to specify the mapping (offset, count) of
332 /// a specific datum within the bitset, without the need of repeating
333 /// the mapping for read and write operations.
334 template <std::size_t Offset, std::size_t Count, typename T> struct bitset_value final {
335 static constexpr std::size_t offset = Offset;
336 static constexpr std::size_t count = Count;
337 using value_type = T;
339 bitset_value(T t)
340 : value(t)
344 bitset_value(const bitset_value &) = default;
345 bitset_value & operator=(const bitset_value &) = default;
347 bitset_value(bitset_value &&) = default;
348 bitset_value & operator=(bitset_value &&) = default;
350 operator T() const { return value; }
352 bitset_value & operator=(T t)
354 value = t;
355 return *this;
358 T value;
361 explicit message(message_id type)
362 : message_type(type)
366 virtual raw get_data() const = 0;
368 /// @{
370 static std::string read_string(
371 const raw & bits, raw::size_type ofs, raw::size_type count_sixbits);
373 static void write_string(
374 raw & bits, raw::size_type ofs, raw::size_type count_sixbits, const std::string & s);
376 /// @}
378 /// @{
380 /// Reads data from the AIS message (bitset).
381 /// This is the `enum` variant.
383 /// @tparam T `bitset_value` type.
384 /// @param[in] bits The AIS message to read from.
385 /// @param[out] t The data read from the message.
387 template <typename T,
388 typename std::enable_if<std::is_enum<typename T::value_type>::value, int>::type = 0>
389 static void get(const raw & bits, T & t)
391 typename std::underlying_type<typename T::value_type>::type tmp;
392 bits.get(tmp, T::offset, T::count);
393 t.value = static_cast<typename T::value_type>(tmp);
396 /// The non `enum` and non `string` variant of `get`.
397 /// @see get
398 template <typename T, typename std::enable_if<!std::is_enum<typename T::value_type>::value
399 && !std::is_same<typename T::value_type, std::string>::value,
400 int>::type
401 = 0>
402 static void get(const raw & bits, T & t)
404 bits.get(t.value, T::offset, T::count);
407 /// The `string` variant of `get`.
408 /// @see get
409 template <typename T, typename std::enable_if<!std::is_enum<typename T::value_type>::value
410 && std::is_same<typename T::value_type, std::string>::value,
411 int>::type
412 = 0>
413 static void get(const raw & bits, T & t)
415 t.value = read_string(bits, T::offset, T::count);
418 /// @}
420 /// @{
422 /// Writes data to the AIS message (bitset).
423 /// This is the `enum` variant.
425 /// @tparam T `bitset_value` type.
426 /// @param[in] bits The AIS message to write to.
427 /// @param[out] t The data to write into the message.
429 template <typename T,
430 typename std::enable_if<std::is_enum<typename T::value_type>::value, int>::type = 0>
431 static void set(raw & bits, const T & t)
433 bits.set(
434 static_cast<typename std::underlying_type<typename T::value_type>::type>(t.value),
435 T::offset, T::count);
438 /// The non `enum` and non `string` variant of `set`.
439 /// @see set
440 template <typename T, typename std::enable_if<!std::is_enum<typename T::value_type>::value
441 && !std::is_same<typename T::value_type, std::string>::value,
442 int>::type
443 = 0>
444 static void set(raw & bits, const T & t)
446 bits.set(t.value, T::offset, T::count);
449 /// The `string` variant of `set`.
450 /// @see set
451 template <typename T, typename std::enable_if<!std::is_enum<typename T::value_type>::value
452 && std::is_same<typename T::value_type, std::string>::value,
453 int>::type
454 = 0>
455 static void set(raw & bits, const T & t)
457 write_string(bits, T::offset, T::count, t.value);
460 /// @}
462 private:
463 message_id message_type;
466 /// Helper function to parse a specific sentence.
467 template <class T> std::unique_ptr<message> message_parse(const raw & bits)
469 return std::unique_ptr<T>(new T{bits});
472 /// @cond DEV
473 namespace detail
475 /// Checks if the specified cast is valid, throws `bad_cast` if not.
476 /// If the pointer is `nullptr`, false returns.
477 template <class T> bool check_cast(const message * s)
479 if (!s)
480 return false;
481 if (s->type() != T::ID)
482 throw std::bad_cast{};
483 return true;
486 /// @endcond
488 /// @{
490 /// Casts the specified message to the message given by the template parameter.
491 /// The object converted only if it is valid and of the correct type. It is not
492 /// possible to cast a message into a completley different one.
494 /// @param[in] s The message object to convert.
495 /// @retval nullptr The specified message is invalid.
496 /// @return The converted message.
497 /// @exception std::bad_cast The specified message has the wrong ID.
498 template <class T> T * message_cast(message * s)
500 return detail::check_cast<T>(s) ? static_cast<T *>(s) : nullptr;
503 /// const variant.
505 /// @see message_cast(message * s)
506 template <class T> const T * message_cast(const message * s)
508 return detail::check_cast<T>(s) ? static_cast<const T *>(s) : nullptr;
511 /// std::unique_ptr variant.
513 /// @see message_cast(message * s)
514 template <class T> T * message_cast(std::unique_ptr<message> & s)
516 return message_cast<T>(s.get());
519 /// const std::unique_ptr variant.
521 /// @see message_cast(message * s)
522 template <class T> const T * message_cast(const std::unique_ptr<message> & s)
524 return message_cast<const T>(s.get());
527 /// @}
529 /// @cond DEV
531 #define MARNAV_AIS_MESSAGE_FRIENDS(s) \
532 friend std::unique_ptr<message> detail::parse_##s(const raw & bits); \
533 template <class T> friend std::unique_ptr<message> message_parse(const raw & bits);
535 #define MARNAV_AIS_DECLARE_MESSAGE_PARSE_FUNC(s) \
536 namespace detail \
538 std::unique_ptr<message> parse_##s(const raw & bits); \
541 #define MARNAV_AIS_DEFINE_MESSAGE_PARSE_FUNC(s) \
542 namespace detail \
544 std::unique_ptr<message> parse_##s(const raw & bits) \
546 return std::unique_ptr<s>(new s{bits}); \
550 /// @endcond
554 #endif