pyxcp 0.23.0__cp313-cp313-win_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyxcp might be problematic. Click here for more details.

Files changed (134) hide show
  1. pyxcp/__init__.py +20 -0
  2. pyxcp/aml/EtasCANMonitoring.a2l +82 -0
  3. pyxcp/aml/EtasCANMonitoring.aml +67 -0
  4. pyxcp/aml/XCP_Common.aml +408 -0
  5. pyxcp/aml/XCPonCAN.aml +78 -0
  6. pyxcp/aml/XCPonEth.aml +33 -0
  7. pyxcp/aml/XCPonFlx.aml +113 -0
  8. pyxcp/aml/XCPonSxI.aml +66 -0
  9. pyxcp/aml/XCPonUSB.aml +106 -0
  10. pyxcp/aml/ifdata_CAN.a2l +20 -0
  11. pyxcp/aml/ifdata_Eth.a2l +11 -0
  12. pyxcp/aml/ifdata_Flx.a2l +94 -0
  13. pyxcp/aml/ifdata_SxI.a2l +13 -0
  14. pyxcp/aml/ifdata_USB.a2l +81 -0
  15. pyxcp/asam/__init__.py +0 -0
  16. pyxcp/asam/types.py +131 -0
  17. pyxcp/asamkeydll.c +116 -0
  18. pyxcp/asamkeydll.sh +2 -0
  19. pyxcp/checksum.py +732 -0
  20. pyxcp/cmdline.py +52 -0
  21. pyxcp/config/__init__.py +1113 -0
  22. pyxcp/config/legacy.py +120 -0
  23. pyxcp/constants.py +47 -0
  24. pyxcp/cpp_ext/__init__.py +0 -0
  25. pyxcp/cpp_ext/bin.hpp +104 -0
  26. pyxcp/cpp_ext/blockmem.hpp +58 -0
  27. pyxcp/cpp_ext/cpp_ext.cp310-win_arm64.pyd +0 -0
  28. pyxcp/cpp_ext/cpp_ext.cp311-win_arm64.pyd +0 -0
  29. pyxcp/cpp_ext/cpp_ext.cp312-win_arm64.pyd +0 -0
  30. pyxcp/cpp_ext/cpp_ext.cp313-win_arm64.pyd +0 -0
  31. pyxcp/cpp_ext/daqlist.hpp +206 -0
  32. pyxcp/cpp_ext/event.hpp +67 -0
  33. pyxcp/cpp_ext/extension_wrapper.cpp +100 -0
  34. pyxcp/cpp_ext/helper.hpp +280 -0
  35. pyxcp/cpp_ext/mcobject.hpp +246 -0
  36. pyxcp/cpp_ext/tsqueue.hpp +46 -0
  37. pyxcp/daq_stim/__init__.py +232 -0
  38. pyxcp/daq_stim/optimize/__init__.py +67 -0
  39. pyxcp/daq_stim/optimize/binpacking.py +41 -0
  40. pyxcp/daq_stim/scheduler.cpp +62 -0
  41. pyxcp/daq_stim/scheduler.hpp +75 -0
  42. pyxcp/daq_stim/stim.cp310-win_arm64.pyd +0 -0
  43. pyxcp/daq_stim/stim.cp311-win_arm64.pyd +0 -0
  44. pyxcp/daq_stim/stim.cp312-win_arm64.pyd +0 -0
  45. pyxcp/daq_stim/stim.cp313-win_arm64.pyd +0 -0
  46. pyxcp/daq_stim/stim.cpp +13 -0
  47. pyxcp/daq_stim/stim.hpp +604 -0
  48. pyxcp/daq_stim/stim_wrapper.cpp +50 -0
  49. pyxcp/dllif.py +100 -0
  50. pyxcp/errormatrix.py +878 -0
  51. pyxcp/examples/conf_can.toml +19 -0
  52. pyxcp/examples/conf_can_user.toml +16 -0
  53. pyxcp/examples/conf_can_vector.json +11 -0
  54. pyxcp/examples/conf_can_vector.toml +11 -0
  55. pyxcp/examples/conf_eth.toml +9 -0
  56. pyxcp/examples/conf_nixnet.json +20 -0
  57. pyxcp/examples/conf_socket_can.toml +12 -0
  58. pyxcp/examples/conf_sxi.json +9 -0
  59. pyxcp/examples/conf_sxi.toml +7 -0
  60. pyxcp/examples/run_daq.py +163 -0
  61. pyxcp/examples/xcp_policy.py +60 -0
  62. pyxcp/examples/xcp_read_benchmark.py +38 -0
  63. pyxcp/examples/xcp_skel.py +49 -0
  64. pyxcp/examples/xcp_unlock.py +38 -0
  65. pyxcp/examples/xcp_user_supplied_driver.py +44 -0
  66. pyxcp/examples/xcphello.py +78 -0
  67. pyxcp/examples/xcphello_recorder.py +107 -0
  68. pyxcp/master/__init__.py +9 -0
  69. pyxcp/master/errorhandler.py +442 -0
  70. pyxcp/master/master.py +2047 -0
  71. pyxcp/py.typed +0 -0
  72. pyxcp/recorder/__init__.py +101 -0
  73. pyxcp/recorder/build_clang.cmd +1 -0
  74. pyxcp/recorder/build_clang.sh +2 -0
  75. pyxcp/recorder/build_gcc.cmd +1 -0
  76. pyxcp/recorder/build_gcc.sh +2 -0
  77. pyxcp/recorder/build_gcc_arm.sh +2 -0
  78. pyxcp/recorder/converter/__init__.py +450 -0
  79. pyxcp/recorder/lz4.c +2829 -0
  80. pyxcp/recorder/lz4.h +879 -0
  81. pyxcp/recorder/lz4hc.c +2041 -0
  82. pyxcp/recorder/lz4hc.h +413 -0
  83. pyxcp/recorder/mio.hpp +1714 -0
  84. pyxcp/recorder/reader.hpp +139 -0
  85. pyxcp/recorder/reco.py +277 -0
  86. pyxcp/recorder/recorder.rst +0 -0
  87. pyxcp/recorder/rekorder.cp310-win_arm64.pyd +0 -0
  88. pyxcp/recorder/rekorder.cp311-win_arm64.pyd +0 -0
  89. pyxcp/recorder/rekorder.cp312-win_arm64.pyd +0 -0
  90. pyxcp/recorder/rekorder.cp313-win_arm64.pyd +0 -0
  91. pyxcp/recorder/rekorder.cpp +59 -0
  92. pyxcp/recorder/rekorder.hpp +274 -0
  93. pyxcp/recorder/setup.py +41 -0
  94. pyxcp/recorder/test_reko.py +34 -0
  95. pyxcp/recorder/unfolder.hpp +1332 -0
  96. pyxcp/recorder/wrap.cpp +189 -0
  97. pyxcp/recorder/writer.hpp +302 -0
  98. pyxcp/scripts/__init__.py +0 -0
  99. pyxcp/scripts/pyxcp_probe_can_drivers.py +20 -0
  100. pyxcp/scripts/xcp_examples.py +64 -0
  101. pyxcp/scripts/xcp_fetch_a2l.py +40 -0
  102. pyxcp/scripts/xcp_id_scanner.py +19 -0
  103. pyxcp/scripts/xcp_info.py +144 -0
  104. pyxcp/scripts/xcp_profile.py +27 -0
  105. pyxcp/scripts/xmraw_converter.py +31 -0
  106. pyxcp/stim/__init__.py +0 -0
  107. pyxcp/tests/test_asam_types.py +24 -0
  108. pyxcp/tests/test_binpacking.py +186 -0
  109. pyxcp/tests/test_can.py +1324 -0
  110. pyxcp/tests/test_checksum.py +95 -0
  111. pyxcp/tests/test_daq.py +193 -0
  112. pyxcp/tests/test_daq_opt.py +426 -0
  113. pyxcp/tests/test_frame_padding.py +156 -0
  114. pyxcp/tests/test_master.py +2006 -0
  115. pyxcp/tests/test_transport.py +81 -0
  116. pyxcp/tests/test_utils.py +30 -0
  117. pyxcp/timing.py +60 -0
  118. pyxcp/transport/__init__.py +10 -0
  119. pyxcp/transport/base.py +440 -0
  120. pyxcp/transport/base_transport.hpp +0 -0
  121. pyxcp/transport/can.py +556 -0
  122. pyxcp/transport/eth.py +219 -0
  123. pyxcp/transport/sxi.py +135 -0
  124. pyxcp/transport/transport_wrapper.cpp +0 -0
  125. pyxcp/transport/usb_transport.py +213 -0
  126. pyxcp/types.py +1000 -0
  127. pyxcp/utils.py +128 -0
  128. pyxcp/vector/__init__.py +0 -0
  129. pyxcp/vector/map.py +82 -0
  130. pyxcp-0.23.0.dist-info/LICENSE +165 -0
  131. pyxcp-0.23.0.dist-info/METADATA +107 -0
  132. pyxcp-0.23.0.dist-info/RECORD +134 -0
  133. pyxcp-0.23.0.dist-info/WHEEL +4 -0
  134. pyxcp-0.23.0.dist-info/entry_points.txt +9 -0
@@ -0,0 +1,100 @@
1
+
2
+ #include <pybind11/chrono.h>
3
+ #include <pybind11/functional.h>
4
+ #include <pybind11/numpy.h>
5
+ #include <pybind11/pybind11.h>
6
+ #include <pybind11/stl.h>
7
+
8
+ #include <cstdint>
9
+
10
+ #include "bin.hpp"
11
+ #include "daqlist.hpp"
12
+ #include "mcobject.hpp"
13
+
14
+ namespace py = pybind11;
15
+ using namespace pybind11::literals;
16
+
17
+ class PyTimestampInfo : public TimestampInfo {
18
+ public:
19
+
20
+ using TimestampInfo::TimestampInfo;
21
+ };
22
+
23
+ PYBIND11_MODULE(cpp_ext, m) {
24
+ m.doc() = "C++ extensions for pyXCP.";
25
+
26
+ //m.def("sleep_ms", &sleep_ms, "milliseconds"_a);
27
+ //m.def("sleep_ns", &sleep_ns, "nanoseconds"_a);
28
+
29
+ py::class_<McObject>(m, "McObject")
30
+ .def(
31
+ py::init<
32
+ std::string_view, std::uint32_t, std::uint8_t, std::uint16_t, const std::string&, const std::vector<McObject>&>(),
33
+ "name"_a, "address"_a, "ext"_a, "length"_a, "data_type"_a = "", "components"_a = std::vector<McObject>()
34
+ )
35
+ .def_property("name", &McObject::get_name, &McObject::set_name)
36
+ .def_property("address", &McObject::get_address, &McObject::set_address)
37
+ .def_property("ext", &McObject::get_ext, &McObject::set_ext)
38
+ .def_property("length", &McObject::get_length, &McObject::set_length)
39
+ .def_property("data_type", &McObject::get_data_type, &McObject::set_data_type)
40
+ .def_property_readonly("components", &McObject::get_components)
41
+
42
+ .def("add_component", &McObject::add_component, "component"_a)
43
+ .def("__eq__", [](const McObject& self, const McObject& other) { return self == other; })
44
+ .def("__repr__", [](const McObject& self) { return to_string(self); })
45
+ .def("__hash__", [](const McObject& self) { return self.get_hash(); })
46
+ ;
47
+
48
+ py::class_<Bin>(m, "Bin")
49
+ .def(py::init<std::uint16_t>(), "size"_a)
50
+ .def_property("size", &Bin::get_size, &Bin::set_size)
51
+ .def_property("residual_capacity", &Bin::get_residual_capacity, &Bin::set_residual_capacity)
52
+ .def_property("entries", &Bin::get_entries, nullptr)
53
+ .def("append", &Bin::append)
54
+
55
+ .def("__repr__", [](const Bin& self) { return to_string(self); })
56
+
57
+ .def("__eq__", [](const Bin& self, const Bin& other) { return self == other; })
58
+
59
+ .def("__len__", [](const Bin& self) { return std::size(self.get_entries()); });
60
+
61
+ py::class_<DaqList>(m, "DaqList")
62
+ .def(
63
+ py::init<std::string_view, std::uint16_t, bool, bool, const std::vector<DaqList::daq_list_initialzer_t>&,
64
+ std::uint8_t, std::uint8_t>(), "name"_a, "event_num"_a, "stim"_a, "enable_timestamps"_a, "measurements"_a,
65
+ "priority"_a=0, "prescaler"_a=1
66
+ )
67
+ .def("__repr__", [](const DaqList& self) { return self.to_string(); })
68
+ .def_property("name", &DaqList::get_name, nullptr)
69
+ .def_property("event_num", &DaqList::get_event_num, &DaqList::set_event_num)
70
+ .def_property("priority", &DaqList::get_priority, nullptr)
71
+ .def_property("prescaler", &DaqList::get_prescaler, nullptr)
72
+ .def_property("stim", &DaqList::get_stim, nullptr)
73
+ .def_property("enable_timestamps", &DaqList::get_enable_timestamps, nullptr)
74
+ .def_property("measurements", &DaqList::get_measurements, nullptr)
75
+ .def_property("measurements_opt", &DaqList::get_measurements_opt, &DaqList::set_measurements_opt)
76
+ .def_property("headers", &DaqList::get_headers, nullptr)
77
+ .def_property("odt_count", &DaqList::get_odt_count, nullptr)
78
+ .def_property("total_entries", &DaqList::get_total_entries, nullptr)
79
+ .def_property("total_length", &DaqList::get_total_length, nullptr);
80
+
81
+ py::enum_<TimestampType>(m, "TimestampType")
82
+ .value("ABSOLUTE_TS", TimestampType::ABSOLUTE_TS)
83
+ .value("RELATIVE_TS", TimestampType::RELATIVE_TS);
84
+
85
+ py::class_<Timestamp>(m, "Timestamp")
86
+ .def(py::init<TimestampType>(), "ts_type"_a)
87
+ .def_property_readonly("absolute", &Timestamp::absolute)
88
+ .def_property_readonly("relative", &Timestamp::relative)
89
+ .def_property_readonly("value", &Timestamp::get_value)
90
+ .def_property_readonly("initial_value", &Timestamp::get_initial_value);
91
+
92
+ py::class_<TimestampInfo, PyTimestampInfo>(m, "TimestampInfo", py::dynamic_attr())
93
+ .def(py::init<std::uint64_t>())
94
+ .def(py::init<std::uint64_t, const std::string&, std::int16_t, std::int16_t>())
95
+
96
+ .def_property_readonly("timestamp_ns", &TimestampInfo::get_timestamp_ns)
97
+ .def_property("utc_offset", &TimestampInfo::get_utc_offset, &TimestampInfo::set_utc_offset)
98
+ .def_property("dst_offset", &TimestampInfo::get_dst_offset, &TimestampInfo::set_dst_offset)
99
+ .def_property("timezone", &TimestampInfo::get_timezone, &TimestampInfo::set_timezone);
100
+ }
@@ -0,0 +1,280 @@
1
+
2
+ #if !defined(__HELPER_HPP)
3
+ #define __HELPER_HPP
4
+
5
+ #if defined(_WIN32) || defined(_WIN64)
6
+
7
+ #else
8
+ #include <sys/time.h>
9
+ #include <time.h>
10
+ #endif
11
+
12
+ #include <bit>
13
+ #include <chrono>
14
+ #include <iostream>
15
+ #include <map>
16
+ #include <utility>
17
+ #include <variant>
18
+
19
+ #if __has_include(<version>)
20
+ #include <version> // Needed for feature testing.
21
+ #endif
22
+
23
+ #ifdef __has_include
24
+ #if __has_include(<stdfloat>)
25
+ #include <stdfloat>
26
+ #endif
27
+ #if defined(__STDCPP_BFLOAT16_T__)
28
+ #define HAS_BFLOAT16 (1)
29
+ #else
30
+ #define HAS_BFLOAT16 (0)
31
+ #endif
32
+
33
+ #if defined(__STDCPP_FLOAT16_T__)
34
+ #define HAS_FLOAT16 (1)
35
+ #else
36
+ #define HAS_FLOAT16 (0)
37
+ #endif
38
+ #else
39
+ #define HAS_FLOAT16 (0)
40
+ #define HAS_BFLOAT16 (0)
41
+ #endif
42
+
43
+ constexpr std::endian target_byteorder() {
44
+ return std::endian::native;
45
+ }
46
+
47
+ template<typename... Args>
48
+ constexpr void DBG_PRINTN(Args &&...args) noexcept {
49
+ ((std::cout << std::forward<Args>(args) << " "), ...);
50
+ }
51
+
52
+ // NOTE: C++23 has std::byteswap()
53
+ constexpr auto _bswap(std::uint64_t v) noexcept {
54
+ return ((v & UINT64_C(0x0000'0000'0000'00FF)) << 56) | ((v & UINT64_C(0x0000'0000'0000'FF00)) << 40) |
55
+ ((v & UINT64_C(0x0000'0000'00FF'0000)) << 24) | ((v & UINT64_C(0x0000'0000'FF00'0000)) << 8) |
56
+ ((v & UINT64_C(0x0000'00FF'0000'0000)) >> 8) | ((v & UINT64_C(0x0000'FF00'0000'0000)) >> 24) |
57
+ ((v & UINT64_C(0x00FF'0000'0000'0000)) >> 40) | ((v & UINT64_C(0xFF00'0000'0000'0000)) >> 56);
58
+ }
59
+
60
+ constexpr auto _bswap(std::uint32_t v) noexcept {
61
+ return ((v & UINT32_C(0x0000'00FF)) << 24) | ((v & UINT32_C(0x0000'FF00)) << 8) | ((v & UINT32_C(0x00FF'0000)) >> 8) |
62
+ ((v & UINT32_C(0xFF00'0000)) >> 24);
63
+ }
64
+
65
+ constexpr auto _bswap(std::uint16_t v) noexcept {
66
+ return ((v & UINT16_C(0x00FF)) << 8) | ((v & UINT16_C(0xFF00)) >> 8);
67
+ }
68
+
69
+ template<typename T>
70
+ inline std::string to_binary(const T &value) {
71
+ std::string result;
72
+
73
+ auto ptr = reinterpret_cast<const std::string::value_type *>(&value);
74
+ for (std::size_t idx = 0; idx < sizeof(T); ++idx) {
75
+ auto ch = ptr[idx];
76
+ result.push_back(ch);
77
+ }
78
+ return result;
79
+ }
80
+
81
+ template<>
82
+ inline std::string to_binary<std::string>(const std::string &value) {
83
+ std::string result;
84
+
85
+ auto ptr = reinterpret_cast<const std::string::value_type *>(value.c_str());
86
+ const std::size_t length = std::size(value);
87
+
88
+ // We are using Pascal strings as serialization format.
89
+ auto len_bin = to_binary(length);
90
+ std::copy(len_bin.begin(), len_bin.end(), std::back_inserter(result));
91
+ for (std::size_t idx = 0; idx < length; ++idx) {
92
+ auto ch = ptr[idx];
93
+ result.push_back(ch);
94
+ }
95
+ return result;
96
+ }
97
+
98
+ inline auto bool_to_string(bool value) {
99
+ return (value == true) ? "True" : "False";
100
+ }
101
+
102
+ inline auto byte_order_to_string(int value) {
103
+ switch (value) {
104
+ case 0:
105
+ return "INTEL";
106
+ case 1:
107
+ return "MOTOROLA";
108
+ default:
109
+ return "<UNKNOWN>";
110
+ }
111
+ return "<UNKNOWN>";
112
+ }
113
+
114
+ template<typename K, typename V>
115
+ static std::map<V, K> reverse_map(const std::map<K, V> &m) {
116
+ std::map<V, K> result;
117
+ for (const auto &[k, v] : m) {
118
+ result[v] = k;
119
+ }
120
+ return result;
121
+ }
122
+
123
+ enum class TimestampType : std::uint8_t {
124
+ ABSOLUTE_TS,
125
+ RELATIVE_TS
126
+ };
127
+
128
+ class TimestampInfo {
129
+ public:
130
+
131
+ TimestampInfo(const TimestampInfo &) = default;
132
+ TimestampInfo(TimestampInfo &&) = default;
133
+ TimestampInfo &operator=(const TimestampInfo &) = default;
134
+ TimestampInfo &operator=(TimestampInfo &&) = default;
135
+ virtual ~TimestampInfo() {}
136
+
137
+ TimestampInfo() : m_timestamp_ns(0), m_timezone{}, m_utc_offset(0), m_dst_offset(0) {
138
+ }
139
+
140
+ TimestampInfo(std::uint64_t timestamp_ns, const std::string &timezone, std::int16_t utc_offset, std::int16_t dst_offset) :
141
+ m_timestamp_ns(timestamp_ns), m_timezone(timezone), m_utc_offset(utc_offset), m_dst_offset(dst_offset) {
142
+ }
143
+
144
+ explicit TimestampInfo(std::uint64_t timestamp_ns) : m_timestamp_ns(timestamp_ns) {
145
+ #if defined(_WIN32) || defined(_WIN64)
146
+ m_timezone = std::chrono::current_zone()->name();
147
+ #else
148
+ tzset();
149
+ m_timezone = tzname[0];
150
+
151
+ #endif // _WIN32 || _WIN64
152
+ }
153
+
154
+ std::string get_timezone() const noexcept {
155
+ return m_timezone;
156
+ }
157
+
158
+ void set_timezone(const std::string &value) noexcept {
159
+ m_timezone = value;
160
+ }
161
+
162
+ std::uint64_t get_timestamp_ns() const noexcept {
163
+ return m_timestamp_ns;
164
+ }
165
+
166
+ void set_utc_offset(std::int16_t value) noexcept {
167
+ m_utc_offset = value;
168
+ }
169
+
170
+ std::int16_t get_utc_offset() const noexcept {
171
+ return m_utc_offset;
172
+ }
173
+
174
+ void set_dst_offset(std::int16_t value) noexcept {
175
+ m_dst_offset = value;
176
+ }
177
+
178
+ std::int16_t get_dst_offset() const noexcept {
179
+ return m_dst_offset;
180
+ }
181
+
182
+ std::string to_string() const noexcept {
183
+ std::stringstream ss;
184
+ ss << "TimestamInfo(\n";
185
+ ss << "\ttimestamp_ns=" << m_timestamp_ns << ",\n";
186
+ ss << "\ttimezone=\"" << m_timezone << "\",\n";
187
+ ss << "\tutc_offset=" << m_utc_offset << ",\n";
188
+ ss << "\tdst_offset=" << m_dst_offset << "\n";
189
+ ss << ");";
190
+ return ss.str();
191
+ }
192
+
193
+ virtual void dummy() const noexcept {};
194
+
195
+ private:
196
+
197
+ std::uint64_t m_timestamp_ns;
198
+ std::string m_timezone{};
199
+ std::int16_t m_utc_offset{ 0 };
200
+ std::int16_t m_dst_offset{ 0 };
201
+ };
202
+
203
+ class Timestamp {
204
+ public:
205
+
206
+ explicit Timestamp(TimestampType ts_type) : m_type(ts_type) {
207
+ m_initial = absolute();
208
+ }
209
+
210
+ Timestamp(const Timestamp &) = default;
211
+ Timestamp(Timestamp &&) = default;
212
+
213
+ std::uint64_t get_value() const noexcept {
214
+ if (m_type == TimestampType::ABSOLUTE_TS) {
215
+ return absolute();
216
+ } else if (m_type == TimestampType::RELATIVE_TS) {
217
+ return relative();
218
+ }
219
+ }
220
+
221
+ std::uint64_t get_initial_value() const noexcept {
222
+ return m_initial;
223
+ }
224
+
225
+ std::uint64_t absolute() const noexcept {
226
+ std::uint64_t current;
227
+
228
+ #if defined(_WIN32) || defined(_WIN64)
229
+ current = std::chrono::duration_cast<std::chrono::nanoseconds>(m_clk.now().time_since_epoch()).count();
230
+ #else
231
+ // On MacOS `clock_gettime_nsec_np` could be used.
232
+ timespec ts;
233
+ clock_gettime(CLOCK_REALTIME, &ts);
234
+ current = static_cast<std::uint64_t>(ts.tv_sec) * 1'000'000'000 + ts.tv_nsec;
235
+ #endif // _WIN32 || _WIN64
236
+ return current;
237
+ }
238
+
239
+ std::uint64_t relative() const noexcept {
240
+ return absolute() - m_initial;
241
+ }
242
+
243
+ private:
244
+
245
+ TimestampType m_type;
246
+ #if defined(_WIN32) || defined(_WIN64)
247
+ std::chrono::utc_clock m_clk;
248
+ #else
249
+
250
+ #endif // _WIN32 || _WIN64
251
+ std::uint64_t m_initial;
252
+ };
253
+
254
+ template<typename T, typename V>
255
+ T variant_get(V&& value) {
256
+
257
+ T result;
258
+
259
+ const T* value_ptr = std::get_if<T>(&value);
260
+ if (value_ptr == nullptr) {
261
+ result = T{};
262
+ }
263
+ else {
264
+ result = *value_ptr;
265
+ }
266
+
267
+ return result;
268
+ }
269
+
270
+ #if 0
271
+ inline void sleep_ms(std::uint64_t milliseconds) {
272
+ std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
273
+ }
274
+
275
+ inline void sleep_ns(std::uint64_t nanoseconds) {
276
+ std::this_thread::sleep_for(std::chrono::nanoseconds(nanoseconds));
277
+ }
278
+ #endif
279
+
280
+ #endif // __HELPER_HPP
@@ -0,0 +1,246 @@
1
+
2
+ #if !defined(__MC_OBJECT_HPP)
3
+ #define __MC_OBJECT_HPP
4
+
5
+ #include <cstdint>
6
+ #include <map>
7
+ #include <optional>
8
+ #include <ranges>
9
+ #include <string>
10
+ #include <vector>
11
+
12
+ #include "helper.hpp"
13
+
14
+ const std::map<const std::string, std::tuple<std::uint16_t, std::uint16_t>> TYPE_MAP = {
15
+ { "U8", { 0, 1 } },
16
+ { "I8", { 1, 1 } },
17
+ { "U16", { 2, 2 } },
18
+ { "I16", { 3, 2 } },
19
+ { "U32", { 4, 4 } },
20
+ { "I32", { 5, 4 } },
21
+ { "U64", { 6, 8 } },
22
+ { "I64", { 7, 8 } },
23
+ { "F32", { 8, 4 } },
24
+ { "F64", { 9, 8 } },
25
+ #if HAS_FLOAT16
26
+ { "F16", { 10, 2 } },
27
+ #endif
28
+ #if HAS_BFLOAT16
29
+ { "BF16", { 11, 2 } },
30
+ #endif
31
+ };
32
+
33
+ enum class TypeCode : std::uint8_t {
34
+ U8,
35
+ I8,
36
+ U16,
37
+ I16,
38
+ U32,
39
+ I32,
40
+ U64,
41
+ I64,
42
+ F32,
43
+ F64,
44
+ F16,
45
+ BF16,
46
+ };
47
+
48
+ const std::map<const std::string, TypeCode> TYPE_TO_TYPE_CODE_MAP = {
49
+ { "U8", TypeCode::U8 },
50
+ { "I8", TypeCode::I8 },
51
+ { "U16", TypeCode::U16 },
52
+ { "I16", TypeCode::I16 },
53
+ { "U32", TypeCode::U32 },
54
+ { "I32", TypeCode::I32 },
55
+ { "U64", TypeCode::U64 },
56
+ { "I64", TypeCode::I64 },
57
+ { "F32", TypeCode::F32 },
58
+ { "F64", TypeCode::F64 },
59
+ #if HAS_FLOAT16
60
+ { "F16", TypeCode::F16 },
61
+ #endif
62
+ #if HAS_BFLOAT16
63
+ { "BF16", TypeCode::BF16 },
64
+ #endif
65
+ };
66
+
67
+ const std::map<std::uint16_t, const std::string> TYPE_MAP_REV = {
68
+ { 0, "U8" },
69
+ { 1, "I8" },
70
+ { 2, "U16" },
71
+ { 3, "I16" },
72
+ { 4, "U32" },
73
+ { 5, "I32" },
74
+ { 6, "U64" },
75
+ { 7, "I64" },
76
+ { 8, "F32" },
77
+ { 9, "F64" },
78
+ #if HAS_FLOAT16
79
+ { 10, "F16" },
80
+ #endif
81
+ #if HAS_BFLOAT16
82
+ { 11, "BF16" },
83
+ #endif
84
+ };
85
+
86
+ inline std::vector<std::string> get_data_types() {
87
+ std::vector<std::string> result;
88
+
89
+ for (const auto& [k, v] : TYPE_MAP) {
90
+ result.emplace_back(k);
91
+ }
92
+
93
+ return result;
94
+ }
95
+
96
+ class McObject {
97
+ public:
98
+
99
+ explicit McObject(
100
+ std::string_view name, std::uint32_t address, std::uint8_t ext, std::uint16_t length, const std::string& data_type,
101
+ const std::vector<McObject>& components = std::vector<McObject>()
102
+ ) :
103
+ m_name(name),
104
+ m_address(address),
105
+ m_ext(ext),
106
+ m_length(length),
107
+ m_data_type(data_type),
108
+ m_type_index(-1),
109
+ m_components(components) {
110
+ if (data_type != "") {
111
+ std::string dt_toupper;
112
+
113
+ dt_toupper.resize(data_type.size());
114
+
115
+ std::transform(data_type.begin(), data_type.end(), dt_toupper.begin(), [](unsigned char c) -> unsigned char {
116
+ return std::toupper(c);
117
+ });
118
+
119
+ if (!TYPE_MAP.contains(dt_toupper)) {
120
+ throw std::runtime_error("Invalid data type: " + data_type);
121
+ }
122
+
123
+ const auto [ti, len] = TYPE_MAP.at(dt_toupper);
124
+ m_type_index = ti;
125
+ m_length = len;
126
+ }
127
+ }
128
+
129
+ McObject(const McObject& obj) = default;
130
+ McObject(McObject&& obj) = default;
131
+ McObject& operator=(const McObject&) = default;
132
+ McObject& operator=(McObject&&) = default;
133
+
134
+ const std::string& get_name() const {
135
+ return m_name;
136
+ }
137
+
138
+ void set_name(std::string_view name) {
139
+ m_name = name;
140
+ }
141
+
142
+ std::uint32_t get_address() const {
143
+ return m_address;
144
+ }
145
+
146
+ void set_address(std::uint32_t address) {
147
+ m_address = address;
148
+ }
149
+
150
+ std::uint8_t get_ext() const {
151
+ return m_ext;
152
+ }
153
+
154
+ void set_ext(std::uint8_t ext) {
155
+ m_ext = ext;
156
+ }
157
+
158
+ const std::string& get_data_type() const {
159
+ return m_data_type;
160
+ }
161
+
162
+ void set_data_type(const std::string& value) {
163
+ m_data_type = value;
164
+ }
165
+
166
+ std::uint16_t get_length() const {
167
+ return m_length;
168
+ }
169
+
170
+ void set_length(std::uint16_t length) {
171
+ m_length = length;
172
+ }
173
+
174
+ std::int32_t get_type_index() const {
175
+ return m_type_index;
176
+ }
177
+
178
+ const std::vector<McObject>& get_components() const {
179
+ return m_components;
180
+ }
181
+
182
+ void add_component(const McObject& obj) {
183
+ m_components.emplace_back(obj);
184
+ }
185
+
186
+ bool operator==(const McObject& other) const {
187
+ return (m_name == other.m_name) && (m_address == other.m_address) && (m_ext == other.m_ext) &&
188
+ (m_length == other.m_length) && (m_data_type == other.m_data_type) &&
189
+ (std::equal(m_components.begin(), m_components.end(), other.m_components.begin(), other.m_components.end()));
190
+ }
191
+
192
+ std::string dumps() const noexcept {
193
+ std::stringstream ss;
194
+
195
+ ss << to_binary(m_name);
196
+ ss << to_binary(m_address);
197
+ ss << to_binary(m_ext);
198
+ ss << to_binary(m_length);
199
+ ss << to_binary(m_data_type);
200
+ ss << to_binary(m_type_index);
201
+
202
+ std::size_t ccount = m_components.size();
203
+ ss << to_binary(ccount);
204
+ for (const auto& obj : m_components) {
205
+ ss << obj.dumps();
206
+ }
207
+ return ss.str();
208
+ }
209
+
210
+ auto get_hash() const noexcept {
211
+ std::hash<std::string> hash_fn;
212
+ return hash_fn(dumps());
213
+ }
214
+
215
+ private:
216
+
217
+ std::string m_name;
218
+ std::uint32_t m_address;
219
+ std::uint8_t m_ext;
220
+ std::uint16_t m_length;
221
+ std::string m_data_type;
222
+ std::int16_t m_type_index;
223
+ std::vector<McObject> m_components{};
224
+ };
225
+
226
+ std::string mc_components_to_string(const std::vector<McObject>& components);
227
+
228
+ std::string to_string(const McObject& obj) {
229
+ std::stringstream ss;
230
+
231
+ ss << "McObject(name='" << obj.get_name() << "', address=" << obj.get_address()
232
+ << ", ext=" << static_cast<std::uint16_t >(obj.get_ext()) << ", data_type='" << obj.get_data_type()
233
+ << "', length=" << obj.get_length() << ", components=[" << mc_components_to_string(obj.get_components()) << "])";
234
+ return ss.str();
235
+ }
236
+
237
+ std::string mc_components_to_string(const std::vector<McObject>& components) {
238
+ std::stringstream ss;
239
+
240
+ for (const auto& obj : components) {
241
+ ss << to_string(obj) << ",\n ";
242
+ }
243
+ return ss.str();
244
+ }
245
+
246
+ #endif // __MC_OBJECT_HPP
@@ -0,0 +1,46 @@
1
+
2
+ #ifndef __TSQUEUE_HPP
3
+ #define __TSQUEUE_HPP
4
+
5
+ #include <condition_variable>
6
+ #include <mutex>
7
+ #include <queue>
8
+
9
+ template<typename T>
10
+ class TsQueue {
11
+ public:
12
+
13
+ TsQueue() = default;
14
+
15
+ TsQueue(const TsQueue& other) noexcept {
16
+ std::scoped_lock lock(other.m_mtx);
17
+ m_queue = other.m_queue;
18
+ }
19
+
20
+ void put(T value) noexcept {
21
+ std::scoped_lock lock(m_mtx);
22
+ m_queue.push(value);
23
+ m_cond.notify_one();
24
+ }
25
+
26
+ std::shared_ptr<T> get() noexcept {
27
+ std::unique_lock lock(m_mtx);
28
+ m_cond.wait(lock, [this] { return !m_queue.empty(); });
29
+ std::shared_ptr<T> result(std::make_shared<T>(m_queue.front()));
30
+ m_queue.pop();
31
+ return result;
32
+ }
33
+
34
+ bool empty() const noexcept {
35
+ std::scoped_lock lock(m_mtx);
36
+ return m_queue.empty();
37
+ }
38
+
39
+ private:
40
+
41
+ mutable std::mutex m_mtx;
42
+ std::queue<T> m_queue;
43
+ std::condition_variable m_cond;
44
+ };
45
+
46
+ #endif // __TSQUEUE_HPP