Dev: preparation script added for code coverage.
[marnav.git] / src / marnav / ais / message_21.cpp
blob6c29b8e9d73892fb36c61125ed81a537bfeafb04
1 #include "message_21.hpp"
2 #include <algorithm>
3 #include <marnav/ais/angle.hpp>
5 namespace marnav
7 namespace ais
9 MARNAV_AIS_DEFINE_MESSAGE_PARSE_FUNC(message_21)
11 message_21::message_21()
12 : message(ID)
13 , name("@@@@@@@@@@@@@@@@@@@@")
17 message_21::message_21(const raw & bits)
18 : message(ID)
19 , name("@@@@@@@@@@@@@@@@@@@@")
21 if ((bits.size() < SIZE_BITS_MIN) || (bits.size() > SIZE_BITS_MAX))
22 throw std::invalid_argument{"invalid number of bits in message_21"};
23 read_data(bits);
26 void message_21::read_data(const raw & bits)
28 get(bits, repeat_indicator);
29 get(bits, mmsi);
30 get(bits, aid_type);
31 get(bits, name);
32 get(bits, position_accuracy);
33 get(bits, longitude_minutes);
34 get(bits, latitude_minutes);
35 get(bits, to_bow);
36 get(bits, to_stern);
37 get(bits, to_port);
38 get(bits, to_starboard);
39 get(bits, epfd_fix);
40 get(bits, utc_second);
41 get(bits, off_position);
42 get(bits, regional);
43 get(bits, raim);
44 get(bits, virtual_aid_flag);
45 get(bits, assigned);
47 auto rest = static_cast<decltype(SIZE_BITS_MAX)>(bits.size()) - SIZE_BITS_MIN;
48 if (rest > 0) {
49 rest = std::min(rest, SIZE_BITS_MAX - SIZE_BITS_MIN);
50 name_extension = read_string(bits, 272, rest / 6);
54 raw message_21::get_data() const
56 raw bits{SIZE_BITS_MIN};
58 bits.set(type(), 0, 6);
59 set(bits, repeat_indicator);
60 set(bits, mmsi);
61 set(bits, aid_type);
62 set(bits, name);
63 set(bits, position_accuracy);
64 set(bits, longitude_minutes);
65 set(bits, latitude_minutes);
66 set(bits, to_bow);
67 set(bits, to_stern);
68 set(bits, to_port);
69 set(bits, to_starboard);
70 set(bits, epfd_fix);
71 set(bits, utc_second);
72 set(bits, off_position);
73 set(bits, regional);
74 set(bits, raim);
75 set(bits, virtual_aid_flag);
76 set(bits, assigned);
78 if (name_extension.size() > 0) {
79 // compute number of bits, must be on a 8-bit boundary
80 auto size = name_extension.size() * 6;
81 if ((size % 8) != 0)
82 size += 8 - (size % 8);
84 if (size <= SIZE_BITS_MAX - SIZE_BITS_MIN) {
85 // append a temporary bitset to the real one
86 raw t{size};
87 write_string(t, 0, name_extension.size(), name_extension);
88 bits.append(t);
92 return bits;
95 std::string message_21::get_name() const { return trim_ais_string(name); }
97 void message_21::set_name(const std::string & t)
99 if (t.size() > 20) {
100 name = t.substr(0, 20);
101 } else {
102 name = t;
106 std::string message_21::get_name_extension() const { return trim_ais_string(name_extension); }
108 void message_21::set_name_extension(const std::string & t)
110 // 88 bits with 6-bit encoding are 14 characters
111 if (t.size() > 14) {
112 name_extension = t.substr(0, 14);
113 } else {
114 name_extension = t;
118 utils::optional<geo::longitude> message_21::get_longitude() const
120 if (longitude_minutes == longitude_not_available)
121 return utils::make_optional<geo::longitude>();
122 return to_geo_longitude(longitude_minutes);
125 utils::optional<geo::latitude> message_21::get_latitude() const
127 if (latitude_minutes == latitude_not_available)
128 return utils::make_optional<geo::latitude>();
129 return to_geo_latitude(latitude_minutes);
132 void message_21::set_longitude(const utils::optional<geo::longitude> & t)
134 longitude_minutes = t ? to_longitude_minutes(t.value()) : longitude_not_available;
137 void message_21::set_latitude(const utils::optional<geo::latitude> & t)
139 latitude_minutes = t ? to_latitude_minutes(t.value()) : latitude_not_available;