NMEA: detectio of the optional tag block in front of a sentence, ignoring it for...
[marnav.git] / src / marnav / nmea / ais_helper.hpp
blob48978a324e6a56e2f1c66af3c9396be35f2c4c10
1 #ifndef __MARNAV__NMEA__AIS_HELPER__HPP__
2 #define __MARNAV__NMEA__AIS_HELPER__HPP__
4 #include <vector>
5 #include <marnav/nmea/vdm.hpp>
6 #include <marnav/nmea/vdo.hpp>
8 namespace marnav
10 namespace nmea
12 /// @{
14 /// @brief Collects payload from proper NMEA sentences.
15 ///
16 /// @note This function assumes, that all sentences in the specified range are
17 /// providing payload (VDM or VDO).
18 ///
19 /// @param[in] begin Iterator pointing to the beginning of the messges to process.
20 /// @param[in] end Iterator pointing after the messages to process (will not be
21 /// processed).
22 /// @return The container with all payload and padding bit information.
23 ///
24 /// std::unique_ptr<nmea::sentence> variant. Example:
25 /// @code
26 /// std::vector<std::unique_ptr<nmea::sentence>> v;
27 /// v.push_back(nmea::make_sentence("..."));
28 /// v.push_back(nmea::make_sentence("..."));
29 /// auto data = nmea::collect_payload(v.begin(), v.end());
30 /// @endcode
31 template <class InputIt, typename std::enable_if<std::is_class<InputIt>::value
32 && std::is_convertible<typename InputIt::value_type,
33 std::unique_ptr<sentence>>::value,
34 int>::type
35 = 0>
36 std::vector<std::pair<std::string, uint32_t>> collect_payload(InputIt begin, InputIt end)
38 std::vector<std::pair<std::string, uint32_t>> v;
39 v.reserve(std::distance(begin, end));
41 for (; begin != end; ++begin) {
42 const auto & t = *begin;
44 // sentence_cast is not dynamic_cast, therefore the class hierarchy
45 // is not detected automatically (the advantage is, it is faster).
46 // this means, we have to check individually for VDM and VDO.
48 if (t->id() == sentence_id::VDM) {
49 const auto s = sentence_cast<nmea::vdm>(t.get());
50 v.push_back(make_pair(s->get_payload(), s->get_n_fill_bits()));
51 } else if (t->id() == sentence_id::VDO) {
52 const auto s = sentence_cast<nmea::vdo>(t.get());
53 v.push_back(make_pair(s->get_payload(), s->get_n_fill_bits()));
54 } else {
55 throw std::runtime_error{"invalid sentence in collect_payload"};
59 return v;
62 /// Object iterator variant. Example:
63 /// @code
64 /// std::vector<nmea::vdm> v; // collect data, for example:
65 /// v.push_back(nmea::vdm{});
66 /// v.push_back(nmea::vdm{});
67 /// auto data = nmea::collect_payload(v.begin(), v.end());
68 /// @endcode
69 template <class InputIt, typename std::enable_if<std::is_class<InputIt>::value
70 && !std::is_convertible<typename InputIt::value_type,
71 std::unique_ptr<sentence>>::value,
72 int>::type
73 = 0>
74 std::vector<std::pair<std::string, uint32_t>> collect_payload(InputIt begin, InputIt end)
76 std::vector<std::pair<std::string, uint32_t>> v;
77 v.reserve(std::distance(begin, end));
78 for (; begin != end; ++begin) {
79 v.push_back(make_pair(begin->get_payload(), begin->get_n_fill_bits()));
81 return v;
84 /// Pointer variant. Example:
85 /// @code
86 /// nmea::vdm v[3]; // initialize them in any way...
87 /// auto data = nmea::collect_payload(v, v + 3);
88 /// @endcode
89 /// or more modern:
90 /// @code
91 /// nmea::vdm v[3]; // initialize them in any way...
92 /// auto data = nmea::collect_payload(std::begin(v), std::end(v));
93 /// @endcode
94 /// this will not compile, because MTW does not provide payload:
95 /// @code
96 /// nmea::mtw v[3];
97 /// auto data = nmea::collect_payload(std::begin(v), std::end(v));
98 /// @endcode
99 template <class InputIt,
100 typename std::enable_if<std::is_pointer<InputIt>::value, int>::type = 0>
101 std::vector<std::pair<std::string, uint32_t>> collect_payload(InputIt begin, InputIt end)
103 std::vector<std::pair<std::string, uint32_t>> v;
104 v.reserve(std::distance(begin, end));
105 for (; begin != end; ++begin) {
106 v.push_back(make_pair(begin->get_payload(), begin->get_n_fill_bits()));
108 return v;
111 /// @}
113 std::vector<std::unique_ptr<nmea::sentence>> make_vdms(
114 const std::vector<std::pair<std::string, uint32_t>> & payload,
115 utils::optional<uint32_t> seq_msg_id = utils::optional<uint32_t>{},
116 ais_channel radio_channel = ais_channel::B);
120 #endif