pyxcp 0.21.10__cp311-cp311-win_amd64.whl → 0.22.23__cp311-cp311-win_amd64.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 (179) hide show
  1. pyxcp/__init__.py +12 -20
  2. pyxcp/aml/EtasCANMonitoring.a2l +82 -83
  3. pyxcp/aml/XCP_Common.aml +0 -1
  4. pyxcp/aml/XCPonUSB.aml +1 -1
  5. pyxcp/aml/ifdata_CAN.a2l +0 -1
  6. pyxcp/aml/ifdata_Eth.a2l +0 -1
  7. pyxcp/aml/ifdata_Flx.a2l +0 -1
  8. pyxcp/aml/ifdata_SxI.a2l +0 -1
  9. pyxcp/aml/ifdata_USB.a2l +0 -1
  10. pyxcp/asam/types.py +4 -4
  11. pyxcp/asamkeydll.c +0 -1
  12. pyxcp/checksum.py +0 -1
  13. pyxcp/cmdline.py +32 -50
  14. pyxcp/config/__init__.py +1100 -0
  15. pyxcp/config/legacy.py +120 -0
  16. pyxcp/constants.py +12 -13
  17. pyxcp/cpp_ext/__init__.py +0 -0
  18. pyxcp/cpp_ext/bin.hpp +104 -0
  19. pyxcp/cpp_ext/blockmem.hpp +58 -0
  20. pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd +0 -0
  21. pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd +0 -0
  22. pyxcp/cpp_ext/cpp_ext.cp38-win_amd64.pyd +0 -0
  23. pyxcp/cpp_ext/cpp_ext.cp39-win_amd64.pyd +0 -0
  24. pyxcp/cpp_ext/daqlist.hpp +200 -0
  25. pyxcp/cpp_ext/event.hpp +67 -0
  26. pyxcp/cpp_ext/extension_wrapper.cpp +96 -0
  27. pyxcp/cpp_ext/helper.hpp +280 -0
  28. pyxcp/cpp_ext/mcobject.hpp +246 -0
  29. pyxcp/cpp_ext/tsqueue.hpp +46 -0
  30. pyxcp/daq_stim/__init__.py +228 -0
  31. pyxcp/daq_stim/optimize/__init__.py +67 -0
  32. pyxcp/daq_stim/optimize/binpacking.py +41 -0
  33. pyxcp/daq_stim/scheduler.cpp +28 -0
  34. pyxcp/daq_stim/scheduler.hpp +75 -0
  35. pyxcp/daq_stim/stim.cp310-win_amd64.pyd +0 -0
  36. pyxcp/daq_stim/stim.cp311-win_amd64.pyd +0 -0
  37. pyxcp/daq_stim/stim.cp38-win_amd64.pyd +0 -0
  38. pyxcp/daq_stim/stim.cp39-win_amd64.pyd +0 -0
  39. pyxcp/daq_stim/stim.cpp +13 -0
  40. pyxcp/daq_stim/stim.hpp +604 -0
  41. pyxcp/daq_stim/stim_wrapper.cpp +48 -0
  42. pyxcp/dllif.py +21 -18
  43. pyxcp/errormatrix.py +5 -3
  44. pyxcp/examples/conf_can.toml +4 -2
  45. pyxcp/examples/conf_can_vector.json +9 -9
  46. pyxcp/examples/conf_can_vector.toml +4 -2
  47. pyxcp/examples/conf_eth.toml +5 -2
  48. pyxcp/examples/conf_nixnet.json +18 -18
  49. pyxcp/examples/conf_sxi.json +7 -7
  50. pyxcp/examples/ex_arrow.py +109 -0
  51. pyxcp/examples/ex_csv.py +85 -0
  52. pyxcp/examples/ex_excel.py +95 -0
  53. pyxcp/examples/ex_mdf.py +124 -0
  54. pyxcp/examples/ex_sqlite.py +128 -0
  55. pyxcp/examples/run_daq.py +148 -0
  56. pyxcp/examples/xcp_policy.py +6 -7
  57. pyxcp/examples/xcp_read_benchmark.py +8 -6
  58. pyxcp/examples/xcp_skel.py +0 -2
  59. pyxcp/examples/xcp_unlock.py +1 -1
  60. pyxcp/examples/xcp_user_supplied_driver.py +1 -2
  61. pyxcp/examples/xcphello.py +6 -3
  62. pyxcp/examples/xcphello_recorder.py +4 -4
  63. pyxcp/master/__init__.py +1 -2
  64. pyxcp/master/errorhandler.py +107 -74
  65. pyxcp/master/master.py +201 -119
  66. pyxcp/py.typed +0 -0
  67. pyxcp/recorder/__init__.py +27 -6
  68. pyxcp/recorder/converter/__init__.py +37 -0
  69. pyxcp/recorder/lz4.c +129 -51
  70. pyxcp/recorder/lz4.h +45 -28
  71. pyxcp/recorder/lz4hc.c +560 -156
  72. pyxcp/recorder/lz4hc.h +1 -1
  73. pyxcp/recorder/mio.hpp +721 -767
  74. pyxcp/recorder/reader.hpp +139 -0
  75. pyxcp/recorder/reco.py +5 -8
  76. pyxcp/recorder/rekorder.cp310-win_amd64.pyd +0 -0
  77. pyxcp/recorder/rekorder.cp311-win_amd64.pyd +0 -0
  78. pyxcp/recorder/rekorder.cp38-win_amd64.pyd +0 -0
  79. pyxcp/recorder/rekorder.cp39-win_amd64.pyd +0 -0
  80. pyxcp/recorder/rekorder.cpp +18 -22
  81. pyxcp/recorder/rekorder.hpp +200 -587
  82. pyxcp/recorder/setup.py +11 -10
  83. pyxcp/recorder/test_reko.py +2 -3
  84. pyxcp/recorder/unfolder.hpp +1332 -0
  85. pyxcp/recorder/wrap.cpp +171 -9
  86. pyxcp/recorder/writer.hpp +302 -0
  87. pyxcp/scripts/pyxcp_probe_can_drivers.py +0 -2
  88. pyxcp/scripts/xcp_examples.py +64 -0
  89. pyxcp/scripts/xcp_fetch_a2l.py +15 -10
  90. pyxcp/scripts/xcp_id_scanner.py +2 -6
  91. pyxcp/scripts/xcp_info.py +101 -63
  92. pyxcp/scripts/xcp_profile.py +27 -0
  93. pyxcp/stim/__init__.py +0 -0
  94. pyxcp/tests/test_asam_types.py +2 -2
  95. pyxcp/tests/test_binpacking.py +186 -0
  96. pyxcp/tests/test_can.py +1132 -38
  97. pyxcp/tests/test_checksum.py +2 -1
  98. pyxcp/tests/test_daq.py +193 -0
  99. pyxcp/tests/test_frame_padding.py +6 -3
  100. pyxcp/tests/test_master.py +42 -31
  101. pyxcp/tests/test_transport.py +12 -12
  102. pyxcp/tests/test_utils.py +2 -5
  103. pyxcp/timing.py +0 -2
  104. pyxcp/transport/__init__.py +9 -9
  105. pyxcp/transport/base.py +149 -127
  106. pyxcp/transport/base_transport.hpp +0 -0
  107. pyxcp/transport/can.py +194 -167
  108. pyxcp/transport/eth.py +80 -82
  109. pyxcp/transport/sxi.py +106 -60
  110. pyxcp/transport/transport_wrapper.cpp +0 -0
  111. pyxcp/transport/usb_transport.py +65 -83
  112. pyxcp/types.py +69 -20
  113. pyxcp/utils.py +47 -16
  114. pyxcp/vector/map.py +1 -3
  115. {pyxcp-0.21.10.dist-info → pyxcp-0.22.23.dist-info}/METADATA +28 -23
  116. pyxcp-0.22.23.dist-info/RECORD +137 -0
  117. {pyxcp-0.21.10.dist-info → pyxcp-0.22.23.dist-info}/WHEEL +1 -1
  118. {pyxcp-0.21.10.dist-info → pyxcp-0.22.23.dist-info}/entry_points.txt +2 -0
  119. pyxcp/config.py +0 -57
  120. pyxcp/cxx/asynchiofactory.hpp +0 -24
  121. pyxcp/cxx/blocking_client.cpp +0 -44
  122. pyxcp/cxx/blocking_socket.cpp +0 -43
  123. pyxcp/cxx/blocking_socket.hpp +0 -558
  124. pyxcp/cxx/concurrent_queue.hpp +0 -60
  125. pyxcp/cxx/eth.hpp +0 -57
  126. pyxcp/cxx/exceptions.hpp +0 -30
  127. pyxcp/cxx/iasyncioservice.hpp +0 -31
  128. pyxcp/cxx/iresource.hpp +0 -17
  129. pyxcp/cxx/isocket.hpp +0 -22
  130. pyxcp/cxx/linux/epoll.cpp +0 -51
  131. pyxcp/cxx/linux/epoll.hpp +0 -87
  132. pyxcp/cxx/linux/lit_tester.cpp +0 -19
  133. pyxcp/cxx/linux/socket.hpp +0 -234
  134. pyxcp/cxx/linux/timeout.hpp +0 -81
  135. pyxcp/cxx/memoryblock.hpp +0 -42
  136. pyxcp/cxx/pool.hpp +0 -81
  137. pyxcp/cxx/poolmgr.cpp +0 -6
  138. pyxcp/cxx/poolmgr.hpp +0 -31
  139. pyxcp/cxx/test_queue.cpp +0 -69
  140. pyxcp/cxx/timestamp.hpp +0 -84
  141. pyxcp/cxx/utils.cpp +0 -38
  142. pyxcp/cxx/utils.hpp +0 -29
  143. pyxcp/cxx/win/iocp.cpp +0 -242
  144. pyxcp/cxx/win/iocp.hpp +0 -42
  145. pyxcp/cxx/win/perhandledata.hpp +0 -24
  146. pyxcp/cxx/win/periodata.hpp +0 -97
  147. pyxcp/cxx/win/socket.hpp +0 -185
  148. pyxcp/cxx/win/timeout.hpp +0 -83
  149. pyxcp/examples/conf_can.json +0 -20
  150. pyxcp/examples/conf_eth.json +0 -8
  151. pyxcp/logger.py +0 -67
  152. pyxcp/tests/test_config.py +0 -62
  153. pyxcp/transport/candriver/__init__.py +0 -2
  154. pyxcp/transport/candriver/pc_canalystii.py +0 -27
  155. pyxcp/transport/candriver/pc_etas.py +0 -25
  156. pyxcp/transport/candriver/pc_gsusb.py +0 -23
  157. pyxcp/transport/candriver/pc_iscan.py +0 -23
  158. pyxcp/transport/candriver/pc_ixxat.py +0 -27
  159. pyxcp/transport/candriver/pc_kvaser.py +0 -39
  160. pyxcp/transport/candriver/pc_neovi.py +0 -31
  161. pyxcp/transport/candriver/pc_nican.py +0 -23
  162. pyxcp/transport/candriver/pc_nixnet.py +0 -23
  163. pyxcp/transport/candriver/pc_pcan.py +0 -25
  164. pyxcp/transport/candriver/pc_seeed.py +0 -28
  165. pyxcp/transport/candriver/pc_serial.py +0 -27
  166. pyxcp/transport/candriver/pc_slcan.py +0 -29
  167. pyxcp/transport/candriver/pc_socketcan.py +0 -23
  168. pyxcp/transport/candriver/pc_systec.py +0 -29
  169. pyxcp/transport/candriver/pc_usb2can.py +0 -30
  170. pyxcp/transport/candriver/pc_vector.py +0 -34
  171. pyxcp/transport/candriver/python_can.py +0 -101
  172. pyxcp/transport/cxx_ext/CMakeLists.txt +0 -51
  173. pyxcp/transport/cxx_ext/setup.py +0 -49
  174. pyxcp/transport/cxx_ext/tests/test_basic_socket.cpp +0 -39
  175. pyxcp/transport/cxx_ext/tests/test_pool.cpp +0 -39
  176. pyxcp/transport/cxx_ext/tests/test_timestamp.cpp +0 -27
  177. pyxcp-0.21.10.dist-info/RECORD +0 -147
  178. rekorder.cp311-win_amd64.pyd +0 -0
  179. {pyxcp-0.21.10.dist-info/licenses → pyxcp-0.22.23.dist-info}/LICENSE +0 -0
@@ -1,125 +1,124 @@
1
1
 
2
-
3
2
  #if !defined(__REKORDER_HPP)
4
- #define __REKORDER_HPP
5
-
6
- #if !defined(STANDALONE_REKORDER)
7
- #define STANDALONE_REKORDER 0
8
- #endif /* STANDALONE_REKORDER */
9
-
10
- #include <array>
11
- #include <atomic>
12
- #include <bitset>
13
- #include <exception>
14
- #include <functional>
15
- #include <optional>
16
- #include <condition_variable>
17
- #include <mutex>
18
- #include <queue>
19
- #include <utility>
20
- #include <string>
21
- #include <stdexcept>
22
-
23
- #include <cerrno>
24
- #include <cstdint>
25
- #include <cstdlib>
26
- #include <cstring>
27
- #include <cstdio>
28
-
29
- #include <ctime>
30
- #include <thread>
31
- #include <vector>
32
-
33
-
34
- #if defined(_WIN32)
35
- #include <io.h>
36
- #include <fcntl.h>
37
-
38
- #include <Windows.h>
39
- #endif /* _WIN32 */
40
-
41
-
42
- #include "lz4.h"
43
- #include "mio.hpp"
44
-
45
- #if STANDALONE_REKORDER == 0
46
- #include <pybind11/pybind11.h>
47
- #include <pybind11/numpy.h>
48
- #include <pybind11/stl.h>
49
-
50
- namespace py = pybind11;
51
- using namespace pybind11::literals;
52
- #endif /* STANDALONE_REKORDER */
53
-
54
- #if !defined(__BIGGEST_ALIGNMENT__)
55
- #define __BIGGEST_ALIGNMENT__ (8)
56
- #endif
57
-
58
-
59
- #define __ALIGNMENT_REQUIREMENT __BIGGEST_ALIGNMENT__
60
- #define __ALIGN alignas(__ALIGNMENT_REQUIREMENT)
3
+ #define __REKORDER_HPP
4
+
5
+ #if !defined(STANDALONE_REKORDER)
6
+ #define STANDALONE_REKORDER 0
7
+ #endif /* STANDALONE_REKORDER */
8
+
9
+ #include <array>
10
+ #include <atomic>
11
+ #include <bit>
12
+ #include <bitset>
13
+ #include <cctype>
14
+ #include <cerrno>
15
+ #include <chrono>
16
+ #include <cstdint>
17
+ #include <cstdio>
18
+ #include <cstdlib>
19
+ #include <cstring>
20
+ #include <ctime>
21
+ #include <exception>
22
+ #include <filesystem>
23
+ #include <functional>
24
+ #include <optional>
25
+ #include <sstream>
26
+ #include <stdexcept>
27
+ #include <string>
28
+ #include <thread>
29
+ #include <utility>
30
+ #include <variant>
31
+ #include <vector>
32
+
33
+ #include "blockmem.hpp"
34
+ #include "event.hpp"
35
+ #include "tsqueue.hpp"
36
+
37
+ #if defined(_WIN32)
38
+ #include <Windows.h>
39
+ #include <fcntl.h>
40
+ #include <io.h>
41
+ #endif /* _WIN32 */
42
+
43
+ #include "lz4hc.h"
44
+ #include "mio.hpp"
45
+
46
+ #if STANDALONE_REKORDER == 0
47
+ #include <pybind11/numpy.h>
48
+ #include <pybind11/pybind11.h>
49
+ #include <pybind11/stl.h>
50
+
51
+ namespace py = pybind11;
52
+ using namespace pybind11::literals;
53
+ #endif /* STANDALONE_REKORDER */
54
+
55
+ #if !defined(__BIGGEST_ALIGNMENT__)
56
+ #define __BIGGEST_ALIGNMENT__ (8)
57
+ #endif
61
58
 
59
+ #define __ALIGNMENT_REQUIREMENT __BIGGEST_ALIGNMENT__
60
+ #define __ALIGN alignas(__ALIGNMENT_REQUIREMENT)
62
61
 
63
- constexpr auto kilobytes(std::uint32_t value) -> std::uint32_t
64
- {
62
+ constexpr auto kilobytes(std::uint32_t value) -> std::uint32_t {
65
63
  return value * 1024;
66
64
  }
67
65
 
68
- constexpr auto megabytes(std::uint32_t value) -> std::uint32_t
69
- {
66
+ constexpr auto megabytes(std::uint32_t value) -> std::uint32_t {
70
67
  return kilobytes(value) * 1024;
71
68
  }
72
69
 
73
- constexpr uint16_t XCP_PAYLOAD_MAX = 0xFFFF;
74
-
75
- /*
76
- byte-order is, where applicable little ending (LSB first).
77
- */
78
- #pragma pack(push)
79
- #pragma pack(1)
80
- struct FileHeaderType
81
- {
82
- uint16_t hdr_size;
83
- uint16_t version;
84
- uint16_t options;
85
- uint32_t num_containers;
86
- uint32_t record_count;
87
- uint32_t size_compressed;
88
- uint32_t size_uncompressed;
70
+ constexpr std::uint16_t XCP_PAYLOAD_MAX = 0xFFFFUL;
71
+
72
+ constexpr std::uint16_t XMRAW_RELATIVE_TIMESTAMPS = 0x0002UL;
73
+ constexpr std::uint16_t XMRAW_HAS_METADATA = 0x0004UL;
74
+
75
+ /*
76
+ byte-order is, where applicable little ending (LSB first).
77
+ */
78
+ #pragma pack(push)
79
+ #pragma pack(1)
80
+
81
+ struct FileHeaderType {
82
+ std::uint16_t hdr_size;
83
+ std::uint16_t version;
84
+ std::uint16_t options;
85
+ std::uint64_t num_containers;
86
+ std::uint64_t record_count;
87
+ std::uint64_t size_compressed;
88
+ std::uint64_t size_uncompressed;
89
89
  };
90
90
 
91
- using HeaderTuple = std::tuple<std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, double>;
91
+ using HeaderTuple = std::tuple<std::uint16_t, std::uint16_t, std::uint64_t, std::uint64_t, std::uint64_t, std::uint64_t, double>;
92
92
 
93
- static_assert(sizeof(FileHeaderType) == 22);
93
+ static_assert(sizeof(FileHeaderType) == 38);
94
94
 
95
- struct ContainerHeaderType
96
- {
97
- uint32_t record_count;
98
- uint32_t size_compressed;
99
- uint32_t size_uncompressed;
95
+ struct ContainerHeaderType {
96
+ std::uint32_t record_count;
97
+ std::uint32_t size_compressed;
98
+ std::uint32_t size_uncompressed;
100
99
  };
101
100
 
102
- using blob_t = unsigned char;
103
-
104
- #if STANDALONE_REKORDER == 1
105
- using payload_t = std::shared_ptr<blob_t[]>;
106
- #else
107
- using payload_t = py::array_t<blob_t>;
108
- #endif /* STANDALONE_REKORDER */
101
+ using blob_t = unsigned char;
102
+ using blob_string = std::basic_string<blob_t>;
109
103
 
110
-
111
- struct frame_header_t
112
- {
113
- uint8_t category {0};
114
- uint16_t counter {0};
115
- double timestamp {0.0};
116
- uint16_t length {0};
104
+ #if STANDALONE_REKORDER == 1
105
+ using payload_t = std::shared_ptr<blob_t[]>;
106
+ #else
107
+ using payload_t = py::array_t<blob_t>;
108
+ #endif /* STANDALONE_REKORDER */
109
+
110
+ struct frame_header_t {
111
+ std::uint8_t category{ 0 };
112
+ std::uint16_t counter{ 0U };
113
+ std::uint64_t timestamp{ 0ULL };
114
+ std::uint16_t length{ 0U };
117
115
  };
118
- #pragma pack(pop)
119
116
 
120
- using FrameTuple = std::tuple<std::uint8_t, std::uint16_t, double, std::uint16_t, payload_t>;
121
- using FrameVector = std::vector<FrameTuple>;
122
- using FrameTupleWriter = std::tuple<std::uint8_t, std::uint16_t, double, std::uint16_t, char *>;
117
+ #pragma pack(pop)
118
+
119
+ using FrameTuple = std::tuple<std::uint8_t, std::uint16_t, std::uint64_t, std::uint16_t, payload_t>;
120
+ using FrameVector = std::vector<FrameTuple>;
121
+ using FrameTupleWriter = std::tuple<std::uint8_t, std::uint16_t, std::uint64_t, std::uint16_t, char*>;
123
122
 
124
123
  enum class FrameCategory : std::uint8_t {
125
124
  META,
@@ -132,530 +131,144 @@ enum class FrameCategory : std::uint8_t {
132
131
  STIM,
133
132
  };
134
133
 
135
- namespace detail
136
- {
137
- const std::string FILE_EXTENSION(".xmraw");
138
- const std::string MAGIC{"ASAMINT::XCP_RAW"};
139
- constexpr auto MAGIC_SIZE = 16;
140
- constexpr auto VERSION = 0x0100;
141
- constexpr auto FILE_HEADER_SIZE = sizeof(FileHeaderType);
142
- constexpr auto CONTAINER_SIZE = sizeof(ContainerHeaderType);
143
- }
144
-
134
+ namespace detail {
135
+ const std::string FILE_EXTENSION(".xmraw");
136
+ const std::string MAGIC{ "ASAMINT::XCP_RAW" };
137
+ constexpr auto MAGIC_SIZE = 16;
138
+ constexpr auto VERSION = 0x0100;
139
+ constexpr auto FILE_HEADER_SIZE = sizeof(FileHeaderType);
140
+ constexpr auto CONTAINER_SIZE = sizeof(ContainerHeaderType);
141
+ } // namespace detail
145
142
 
146
- constexpr auto file_header_size() -> std::uint32_t {
143
+ constexpr auto file_header_size() -> std::uint64_t {
147
144
  return (detail::FILE_HEADER_SIZE + detail::MAGIC_SIZE);
148
145
  }
149
146
 
150
- using rounding_func_t = std::function<std::uint32_t(std::uint32_t)>;
147
+ using rounding_func_t = std::function<std::uint64_t(std::uint64_t)>;
151
148
 
152
- inline rounding_func_t create_rounding_func(std::uint32_t multiple) {
153
- return [multiple](std::uint32_t value) {
154
- return (value + (multiple - 1)) & ~(multiple -1 );
149
+ inline rounding_func_t create_rounding_func(std::uint64_t multiple) {
150
+ return [multiple](std::uint64_t value) {
151
+ return (value + (multiple - 1)) & ~(multiple - 1);
155
152
  };
156
153
  }
157
154
 
158
155
  const auto round_to_alignment = create_rounding_func(__ALIGNMENT_REQUIREMENT);
159
156
 
160
-
161
- inline void _fcopy(char * dest, char const * src, std::uint32_t n) noexcept
162
- {
163
- for (std::uint32_t i = 0; i < n; ++i) {
157
+ inline void _fcopy(char* dest, char const * src, std::uint64_t n) noexcept {
158
+ for (std::uint64_t i = 0; i < n; ++i) {
164
159
  dest[i] = src[i];
165
160
  }
166
161
  }
167
162
 
168
- #if STANDALONE_REKORDER == 1
169
- inline blob_t * get_payload_ptr(const payload_t& payload) noexcept {
170
- return payload.get();
171
- }
172
-
173
- inline payload_t create_payload(std::uint32_t size, blob_t const * data) noexcept {
174
- auto pl = std::make_shared<blob_t[]>(size);
175
- _fcopy(reinterpret_cast<char*>(pl.get()), reinterpret_cast<char const*>(data), size);
176
- return pl;
177
- }
178
- #else
179
- inline payload_t create_payload(std::uint32_t size, blob_t const * data) {
180
- return py::array_t<blob_t>(size, data);
181
- }
182
-
183
- inline blob_t * get_payload_ptr(const payload_t& payload) noexcept {
184
- py::buffer_info buf = payload.request();
185
-
186
- return static_cast<blob_t *>(buf.ptr);
187
- }
188
- #endif /* STANDALONE_REKORDER */
189
-
190
- inline void hexdump(blob_t const * buf, std::uint16_t sz) {
191
- for (std::uint16_t idx = 0; idx < sz; ++idx)
192
- {
193
- printf("%02X ", buf[idx]);
194
- }
195
- printf("\n\r");
163
+ #if STANDALONE_REKORDER == 1
164
+ inline blob_t* get_payload_ptr(const payload_t& payload) noexcept {
165
+ return payload.get();
196
166
  }
197
167
 
168
+ inline payload_t create_payload(std::uint64_t size, blob_t const * data) noexcept {
169
+ auto pl = std::make_shared<blob_t[]>(size);
170
+ _fcopy(reinterpret_cast<char*>(pl.get()), reinterpret_cast<char const *>(data), size);
171
+ return pl;
172
+ }
173
+ #else
174
+ inline payload_t create_payload(std::uint64_t size, blob_t const * data) {
175
+ return py::array_t<blob_t>(size, data);
176
+ }
198
177
 
199
- template <typename T>
200
- class TsQueue {
201
- public:
202
- TsQueue() = default;
203
-
204
- TsQueue(const TsQueue& other) noexcept {
205
- std::scoped_lock lock(other.m_mtx);
206
- m_queue = other.m_queue;
207
- }
208
-
209
- void put(T value) noexcept {
210
- std::scoped_lock lock(m_mtx);
211
- m_queue.push(value);
212
- m_cond.notify_one();
213
- }
214
-
215
- std::shared_ptr<T> get() noexcept {
216
- std::unique_lock lock(m_mtx);
217
- m_cond.wait(lock, [this]{return !m_queue.empty();});
218
- std::shared_ptr<T> result(std::make_shared<T>(m_queue.front()));
219
- m_queue.pop();
220
- return result;
221
- }
222
-
223
- bool empty() const noexcept {
224
- std::scoped_lock lock(m_mtx);
225
- return m_queue.empty();
226
- }
227
-
228
- private:
229
- mutable std::mutex m_mtx;
230
- std::queue<T> m_queue;
231
- std::condition_variable m_cond;
232
- };
233
-
234
-
235
- class Event {
236
- public:
237
-
238
- Event(const Event& other) noexcept {
239
- std::scoped_lock lock(other.m_mtx);
240
- m_flag = other.m_flag;
241
- }
242
-
243
- ~Event() = default;
244
- Event() = default;
245
-
246
- void signal() noexcept {
247
- std::scoped_lock lock(m_mtx);
248
- m_flag = true;
249
- m_cond.notify_one();
250
- }
251
-
252
- void wait() noexcept {
253
- std::unique_lock lock(m_mtx);
254
- m_cond.wait(lock, [this]{return m_flag;});
255
- m_flag = false;
256
- }
257
-
258
- bool state() const noexcept {
259
- std::scoped_lock lock(m_mtx);
260
- return m_flag;
261
- }
262
-
263
- private:
264
- mutable std::mutex m_mtx {};
265
- bool m_flag {false};
266
- std::condition_variable m_cond {};
267
- };
268
-
269
-
270
- /*
271
- *
272
- * Super simplicistic block memory manager.
273
- *
274
- */
275
- template <typename T, int _IS, int _NB>
276
- class BlockMemory {
277
-
278
- public:
279
-
280
- using mem_block_t = std::array<T, _IS>;
281
-
282
- explicit BlockMemory() noexcept : m_memory{nullptr}, m_allocation_count{0} {
283
- m_memory = new T[_IS * _NB];
284
- }
285
-
286
- ~BlockMemory() noexcept {
287
- if (m_memory) {
288
- delete[] m_memory;
289
- }
290
- }
291
- BlockMemory(const BlockMemory&) = delete;
292
-
293
- T * acquire() noexcept {
294
- const std::scoped_lock lock(m_mtx);
295
-
296
- if (m_allocation_count >= _NB) {
297
- return nullptr;
298
- }
299
- T * ptr = reinterpret_cast<T *>(m_memory + (m_allocation_count * _IS));
300
- m_allocation_count++;
301
- return ptr;
302
- }
303
-
304
- void release() noexcept {
305
- const std::scoped_lock lock(m_mtx);
306
- if (m_allocation_count == 0) {
307
- return;
308
- }
309
- m_allocation_count--;
310
- }
178
+ inline blob_t* get_payload_ptr(const payload_t& payload) noexcept {
179
+ py::buffer_info buf = payload.request();
311
180
 
312
- private:
181
+ return static_cast<blob_t*>(buf.ptr);
182
+ }
183
+ #endif /* STANDALONE_REKORDER */
313
184
 
314
- T * m_memory;
315
- std::uint32_t m_allocation_count;
316
- std::mutex m_mtx;
185
+ #ifdef _WIN32
186
+ inline std::string error_string(std::string_view func, std::error_code error_code) {
187
+ LPSTR messageBuffer = nullptr;
188
+ std::ostringstream ss;
317
189
 
318
- };
190
+ size_t size = FormatMessageA(
191
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
192
+ static_cast<DWORD>(error_code.value()), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL
193
+ );
319
194
 
195
+ std::string message(messageBuffer, size);
196
+ LocalFree(messageBuffer);
320
197
 
321
- /**
322
- */
323
- class XcpLogFileWriter
324
- {
325
- public:
326
- explicit XcpLogFileWriter(const std::string& file_name, uint32_t prealloc = 10UL, uint32_t chunk_size = 1) noexcept
327
- {
328
- if (!file_name.ends_with(detail::FILE_EXTENSION)) {
329
- m_file_name = file_name + detail::FILE_EXTENSION;
330
- } else {
331
- m_file_name = file_name;
332
- }
333
-
334
- #if defined(_WIN32)
335
- m_fd = CreateFileA(
336
- m_file_name.c_str(),
337
- GENERIC_READ | GENERIC_WRITE,
338
- 0,
339
- (LPSECURITY_ATTRIBUTES)nullptr,
340
- CREATE_ALWAYS,
341
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
342
- nullptr
343
- );
344
- #else
345
- m_fd = open(m_file_name.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0666);
346
- #endif
347
- truncate(megabytes(prealloc));
348
- m_mmap = new mio::mmap_sink(m_fd);
349
- m_chunk_size = megabytes(chunk_size);
350
- m_intermediate_storage = new blob_t[m_chunk_size + megabytes(1)];
351
- m_offset = detail::FILE_HEADER_SIZE + detail::MAGIC_SIZE;
352
-
353
- start_thread();
354
- }
198
+ ss << "[ERROR] ";
199
+ ss << func << ": ";
200
+ ss << message;
201
+ return ss.str();
202
+ }
355
203
 
356
- ~XcpLogFileWriter() noexcept {
357
- finalize();
358
- #ifdef __APPLE__
359
- if (collector_thread.joinable()) {
360
- collector_thread.join();
361
- }
362
- #endif
363
- }
204
+ inline std::error_code get_last_error() {
205
+ return std::error_code(GetLastError(), std::system_category());
206
+ }
364
207
 
365
- void finalize() {
366
- if (!m_finalized) {
367
- m_finalized = true;
368
- stop_thread();
369
- if (m_container_record_count) {
370
- compress_frames();
371
- }
372
- write_header(detail::VERSION, 0x0000, m_num_containers, m_record_count, m_total_size_compressed, m_total_size_uncompressed);
373
- m_mmap->unmap();
374
- truncate(m_offset);
375
- #if defined(_WIN32)
376
- CloseHandle(m_fd);
377
- #else
378
- close(m_fd);
379
- #endif
380
- delete m_mmap;
381
- delete[] m_intermediate_storage;
382
- }
383
- }
208
+ #else
209
+ inline std::string error_string(std::string_view func, std::error_code error_code) {
210
+ std::ostringstream ss;
384
211
 
385
- void add_frame(uint8_t category, uint16_t counter, double timestamp, uint16_t length, char const * data) noexcept {
386
- auto payload= new char[length];
387
- //auto payload = mem.acquire();
212
+ auto message = strerror(static_cast<int>(error_code.value()));
388
213
 
389
- _fcopy(payload, data, length);
390
- my_queue.put(
391
- std::make_tuple(category, counter, timestamp, length, payload)
392
- );
393
- }
214
+ ss << "[ERROR] ";
215
+ ss << func << ": ";
216
+ ss << message;
217
+ return ss.str();
218
+ }
394
219
 
395
- protected:
396
- void truncate(off_t size) const noexcept
397
- {
398
- #if defined(_WIN32)
399
- if (SetFilePointer(m_fd, size, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
400
- // TODO: Errorhandling.
401
- }
402
- if (SetEndOfFile(m_fd) == 0) {
403
- // TODO: Errorhandling.
404
- }
405
- #else
406
- ftruncate(m_fd, size);
407
- #endif
408
- }
220
+ inline std::error_code get_last_error() {
221
+ return std::error_code(errno, std::system_category());
222
+ }
409
223
 
410
- blob_t * ptr(std::uint32_t pos = 0) const noexcept
411
- {
412
- return (blob_t *)(m_mmap->data() + pos);
413
- }
224
+ #endif // _WIN32
414
225
 
415
- template<typename T>
416
- void store_im(T const * data, std::uint32_t length) noexcept {
417
- _fcopy(reinterpret_cast<char*>(m_intermediate_storage + m_intermediate_storage_offset), reinterpret_cast<char const*>(data), length);
418
- m_intermediate_storage_offset += length;
419
- }
420
-
421
- void compress_frames() {
422
- auto container = ContainerHeaderType{};
423
- //printf("Compressing %u frames... [%d]\n", m_container_record_count, m_intermediate_storage_offset);
424
- const int cp_size = ::LZ4_compress_default(
425
- reinterpret_cast<char const*>(m_intermediate_storage), reinterpret_cast<char *>(ptr(m_offset + detail::CONTAINER_SIZE)),
426
- m_intermediate_storage_offset, LZ4_COMPRESSBOUND(m_intermediate_storage_offset)
427
- );
428
- if (cp_size < 0) {
429
- throw std::runtime_error("LZ4 compression failed.");
430
- }
431
- //printf("comp: %d %d [%f]\n", m_intermediate_storage_offset, cp_size, double(m_intermediate_storage_offset) / double(cp_size));
432
- container.record_count = m_container_record_count;
433
- container.size_compressed = cp_size;
434
- container.size_uncompressed = m_container_size_uncompressed;
435
- _fcopy(reinterpret_cast<char *>(ptr(m_offset)), reinterpret_cast<char const*>(&container), detail::CONTAINER_SIZE);
436
- m_offset += (detail::CONTAINER_SIZE + cp_size);
437
- m_total_size_uncompressed += m_container_size_uncompressed;
438
- m_total_size_compressed += cp_size;
439
- m_record_count += m_container_record_count;
440
- m_container_size_uncompressed = 0;
441
- m_container_size_compressed = 0;
442
- m_container_record_count = 0;
443
- m_intermediate_storage_offset = 0;
444
- m_num_containers += 1;
445
- }
226
+ inline std::string& ltrim(std::string& s) {
227
+ auto it = std::find_if(s.begin(), s.end(), [](char c) { return !std::isspace<char>(c, std::locale::classic()); });
228
+ s.erase(s.begin(), it);
229
+ return s;
230
+ }
446
231
 
447
- void write_bytes(std::uint32_t pos, std::uint32_t count, char const * buf) const noexcept
448
- {
449
- auto addr = reinterpret_cast<char *>(ptr(pos));
232
+ inline std::string& rtrim(std::string& s) {
233
+ auto it = std::find_if(s.rbegin(), s.rend(), [](char c) { return !std::isspace<char>(c, std::locale::classic()); });
234
+ s.erase(it.base(), s.end());
235
+ return s;
236
+ }
450
237
 
451
- _fcopy(addr, buf, count);
452
- }
238
+ inline std::string& trim(std::string& s) {
239
+ return ltrim(rtrim(s));
240
+ }
453
241
 
454
- void write_header(uint16_t version, uint16_t options, uint32_t num_containers,
455
- uint32_t record_count, uint32_t size_compressed, uint32_t size_uncompressed) noexcept {
456
- auto header = FileHeaderType{};
457
- write_bytes(0x00000000UL, detail::MAGIC_SIZE, detail::MAGIC.c_str());
458
- header.hdr_size = detail::FILE_HEADER_SIZE + detail::MAGIC_SIZE;
459
- header.version = version;
460
- header.options = options;
461
- header.num_containers = num_containers;
462
- header.record_count = record_count;
463
- header.size_compressed = size_compressed;
464
- header.size_uncompressed = size_uncompressed;
465
- write_bytes(0x00000000UL + detail::MAGIC_SIZE, detail::FILE_HEADER_SIZE, reinterpret_cast<char const*>(&header));
466
- }
242
+ inline std::string current_timestamp() {
243
+ std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
467
244
 
468
- bool start_thread() noexcept {
469
- if (collector_thread.joinable()) {
470
- return false;
471
- }
472
- stop_collector_thread_flag = false;
473
- #ifdef __APPLE__
474
- collector_thread = std::thread([this]() {
475
- #else
476
- collector_thread = std::jthread([this]() {
477
- #endif
478
- while (!stop_collector_thread_flag) {
479
- auto item = my_queue.get();
480
- const auto content = item.get();
481
- if (stop_collector_thread_flag == true)
482
- {
483
- break;
484
- }
485
- const auto [category, counter, timestamp, length, payload] = *content;
486
- const frame_header_t frame{ category, counter, timestamp, length };
487
- store_im(&frame, sizeof(frame));
488
- store_im(payload, length);
489
- delete[] payload;
490
- m_container_record_count += 1;
491
- m_container_size_uncompressed += (sizeof(frame) + length);
492
- if (m_container_size_uncompressed > m_chunk_size) {
493
- compress_frames();
494
- }
495
- }
496
- });
497
- return true;
498
- }
245
+ #if defined(_MSC_VER)
246
+ errno_t err;
247
+ char tbuf[128];
248
+ std::string result{};
499
249
 
500
- bool stop_thread() noexcept {
501
- if (!collector_thread.joinable()) {
502
- return false;
503
- }
504
- stop_collector_thread_flag = true;
505
- my_queue.put(FrameTupleWriter{}); // Put something into the queue, otherwise the thread will hang forever.
506
- collector_thread.join();
507
- return true;
250
+ err = ::ctime_s(tbuf, 128, &now);
251
+ if (err == 0) {
252
+ result = tbuf;
508
253
  }
509
254
 
510
- private:
511
- std::string m_file_name;
512
- std::uint32_t m_offset{0};
513
- std::uint32_t m_chunk_size{0};
514
- std::uint32_t m_num_containers{0};
515
- std::uint32_t m_record_count{0UL};
516
- std::uint32_t m_container_record_count{0UL};
517
- std::uint32_t m_total_size_uncompressed{0UL};
518
- std::uint32_t m_total_size_compressed{0UL};
519
- std::uint32_t m_container_size_uncompressed{0UL};
520
- std::uint32_t m_container_size_compressed{0UL};
521
- __ALIGN blob_t * m_intermediate_storage{nullptr};
522
- std::uint32_t m_intermediate_storage_offset{0};
523
- mio::file_handle_type m_fd{INVALID_HANDLE_VALUE};
524
- mio::mmap_sink * m_mmap{nullptr};
525
- bool m_finalized{false};
526
- #ifdef __APPLE__
527
- std::thread collector_thread{};
528
255
  #else
529
- std::jthread collector_thread{};
256
+ std::string result{ ::ctime(&now) };
530
257
  #endif
531
- std::mutex mtx;
532
- TsQueue<FrameTupleWriter> my_queue;
533
- BlockMemory<char, XCP_PAYLOAD_MAX, 16> mem{};
534
- std::atomic_bool stop_collector_thread_flag{false};
535
- };
536
-
537
-
538
- /**
539
- */
540
- class XcpLogFileReader
541
- {
542
- public:
543
- explicit XcpLogFileReader(const std::string& file_name)
544
- {
545
- if (!file_name.ends_with(detail::FILE_EXTENSION)) {
546
- m_file_name = file_name + detail::FILE_EXTENSION;
547
- } else {
548
- m_file_name = file_name;
549
- }
550
-
551
- m_mmap = new mio::mmap_source(m_file_name);
552
- blob_t magic[detail::MAGIC_SIZE + 1];
553
-
554
- read_bytes(0UL, detail::MAGIC_SIZE, magic);
555
- if (memcmp(detail::MAGIC.c_str(), magic, detail::MAGIC_SIZE) != 0) {
556
- throw std::runtime_error("Invalid file magic.");
557
- }
558
- m_offset = detail::MAGIC_SIZE;
559
-
560
- read_bytes(m_offset, detail::FILE_HEADER_SIZE, reinterpret_cast<blob_t*>(&m_header));
561
- //printf("Sizes: %u %u %.3f\n", m_header.size_uncompressed,
562
- // m_header.size_compressed,
563
- // float(m_header.size_uncompressed) / float(m_header.size_compressed));
564
- if (m_header.hdr_size != detail::FILE_HEADER_SIZE + detail::MAGIC_SIZE)
565
- {
566
- throw std::runtime_error("File header size does not match.");
567
- }
568
- if (detail::VERSION != m_header.version)
569
- {
570
- throw std::runtime_error("File version mismatch.");
571
- }
572
-
573
- if (m_header.num_containers < 1) {
574
- throw std::runtime_error("At least one container required.");
575
- }
576
-
577
- m_offset += detail::FILE_HEADER_SIZE;
578
- }
579
258
 
580
- [[nodiscard]]
581
- FileHeaderType get_header() const noexcept {
582
- return m_header;
583
- }
584
-
585
- [[nodiscard]]
586
- auto get_header_as_tuple() const noexcept -> HeaderTuple {
587
- auto hdr = get_header();
588
-
589
- return std::make_tuple(
590
- hdr.num_containers,
591
- hdr.record_count,
592
- hdr.size_uncompressed,
593
- hdr.size_compressed,
594
- (double)((std::uint64_t)(((double)hdr.size_uncompressed / (double)hdr.size_compressed * 100.0) + 0.5)) / 100.0
595
- );
596
- }
597
-
598
- void reset() noexcept {
599
- m_current_container = 0;
600
- m_offset = file_header_size();
601
- }
602
-
603
- std::optional<FrameVector> next_block() {
604
- auto container = ContainerHeaderType{};
605
- auto frame = frame_header_t{};
606
- std::uint32_t boffs = 0;
607
- auto result = FrameVector{};
608
- payload_t payload;
609
-
610
- if (m_current_container >= m_header.num_containers) {
611
- return std::nullopt;
612
- }
613
- read_bytes(m_offset, detail::CONTAINER_SIZE, reinterpret_cast<blob_t*>(&container));
614
- __ALIGN auto buffer = new blob_t[container.size_uncompressed];
615
- m_offset += detail::CONTAINER_SIZE;
616
- result.reserve(container.record_count);
617
- const int uc_size = ::LZ4_decompress_safe(reinterpret_cast<char const*>(ptr(m_offset)), reinterpret_cast<char *>(buffer), container.size_compressed, container.size_uncompressed);
618
- if (uc_size < 0) {
619
- throw std::runtime_error("LZ4 decompression failed.");
620
- }
621
- boffs = 0;
622
- for (std::uint32_t idx = 0; idx < container.record_count; ++idx) {
623
- _fcopy(reinterpret_cast<char *>(&frame), reinterpret_cast<char const*>(&(buffer[boffs])), sizeof(frame_header_t));
624
- boffs += sizeof(frame_header_t);
625
- result.emplace_back(frame.category, frame.counter, frame.timestamp, frame.length, create_payload(frame.length, &buffer[boffs]));
626
- boffs += frame.length;
627
- }
628
- m_offset += container.size_compressed;
629
- m_current_container += 1;
630
- delete[] buffer;
631
-
632
- return std::optional<FrameVector>{result};
633
- }
634
-
635
- ~XcpLogFileReader() noexcept
636
- {
637
- delete m_mmap;
638
- }
639
-
640
- protected:
641
- [[nodiscard]]
642
- blob_t const *ptr(std::uint32_t pos = 0) const
643
- {
644
- return reinterpret_cast<blob_t const*>(m_mmap->data() + pos);
645
- }
259
+ // result.erase(std::remove_if(result.begin(), result.end(), ::isspace), result.end());
260
+ return trim(result);
261
+ }
646
262
 
647
- void read_bytes(std::uint32_t pos, std::uint32_t count, blob_t * buf) const
648
- {
649
- auto addr = reinterpret_cast<char const*>(ptr(pos));
650
- _fcopy(reinterpret_cast<char *>(buf), addr, count);
263
+ inline void hexdump(blob_t const * buf, std::uint16_t sz) {
264
+ for (std::uint16_t idx = 0; idx < sz; ++idx) {
265
+ printf("%02X ", buf[idx]);
651
266
  }
267
+ printf("\n\r");
268
+ }
652
269
 
653
- private:
654
- std::string m_file_name;
655
- std::uint32_t m_offset{0};
656
- std::uint32_t m_current_container{0};
657
- mio::mmap_source * m_mmap{nullptr};
658
- FileHeaderType m_header;
659
- };
270
+ #include "reader.hpp"
271
+ #include "unfolder.hpp"
272
+ #include "writer.hpp"
660
273
 
661
- #endif // __REKORDER_HPP
274
+ #endif // __REKORDER_HPP