pyxcp 0.21.9__cp38-cp38-win_amd64.whl → 0.22.23__cp38-cp38-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.
- pyxcp/__init__.py +12 -20
- pyxcp/aml/EtasCANMonitoring.a2l +82 -83
- pyxcp/aml/XCP_Common.aml +0 -1
- pyxcp/aml/XCPonUSB.aml +1 -1
- pyxcp/aml/ifdata_CAN.a2l +0 -1
- pyxcp/aml/ifdata_Eth.a2l +0 -1
- pyxcp/aml/ifdata_Flx.a2l +0 -1
- pyxcp/aml/ifdata_SxI.a2l +0 -1
- pyxcp/aml/ifdata_USB.a2l +0 -1
- pyxcp/asam/types.py +4 -4
- pyxcp/asamkeydll.c +0 -1
- pyxcp/checksum.py +0 -1
- pyxcp/cmdline.py +32 -50
- pyxcp/config/__init__.py +1100 -0
- pyxcp/config/legacy.py +120 -0
- pyxcp/constants.py +12 -13
- pyxcp/cpp_ext/__init__.py +0 -0
- pyxcp/cpp_ext/bin.hpp +104 -0
- pyxcp/cpp_ext/blockmem.hpp +58 -0
- pyxcp/cpp_ext/cpp_ext.cp38-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/daqlist.hpp +200 -0
- pyxcp/cpp_ext/event.hpp +67 -0
- pyxcp/cpp_ext/extension_wrapper.cpp +96 -0
- pyxcp/cpp_ext/helper.hpp +280 -0
- pyxcp/cpp_ext/mcobject.hpp +246 -0
- pyxcp/cpp_ext/tsqueue.hpp +46 -0
- pyxcp/daq_stim/__init__.py +228 -0
- pyxcp/daq_stim/optimize/__init__.py +67 -0
- pyxcp/daq_stim/optimize/binpacking.py +41 -0
- pyxcp/daq_stim/scheduler.cpp +28 -0
- pyxcp/daq_stim/scheduler.hpp +75 -0
- pyxcp/daq_stim/stim.cp38-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cpp +13 -0
- pyxcp/daq_stim/stim.hpp +604 -0
- pyxcp/daq_stim/stim_wrapper.cpp +48 -0
- pyxcp/dllif.py +21 -18
- pyxcp/errormatrix.py +5 -3
- pyxcp/examples/conf_can.toml +4 -2
- pyxcp/examples/conf_can_vector.json +9 -9
- pyxcp/examples/conf_can_vector.toml +4 -2
- pyxcp/examples/conf_eth.toml +5 -2
- pyxcp/examples/conf_nixnet.json +18 -18
- pyxcp/examples/conf_sxi.json +7 -7
- pyxcp/examples/ex_arrow.py +109 -0
- pyxcp/examples/ex_csv.py +85 -0
- pyxcp/examples/ex_excel.py +95 -0
- pyxcp/examples/ex_mdf.py +124 -0
- pyxcp/examples/ex_sqlite.py +128 -0
- pyxcp/examples/run_daq.py +148 -0
- pyxcp/examples/xcp_policy.py +6 -7
- pyxcp/examples/xcp_read_benchmark.py +8 -6
- pyxcp/examples/xcp_skel.py +0 -2
- pyxcp/examples/xcp_unlock.py +1 -1
- pyxcp/examples/xcp_user_supplied_driver.py +1 -2
- pyxcp/examples/xcphello.py +6 -3
- pyxcp/examples/xcphello_recorder.py +4 -4
- pyxcp/master/__init__.py +1 -2
- pyxcp/master/errorhandler.py +107 -74
- pyxcp/master/master.py +196 -114
- pyxcp/py.typed +0 -0
- pyxcp/recorder/__init__.py +27 -6
- pyxcp/recorder/converter/__init__.py +37 -0
- pyxcp/recorder/lz4.c +129 -51
- pyxcp/recorder/lz4.h +45 -28
- pyxcp/recorder/lz4hc.c +560 -156
- pyxcp/recorder/lz4hc.h +1 -1
- pyxcp/recorder/mio.hpp +721 -767
- pyxcp/recorder/reader.hpp +139 -0
- pyxcp/recorder/reco.py +5 -8
- pyxcp/recorder/rekorder.cp38-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cpp +18 -22
- pyxcp/recorder/rekorder.hpp +200 -587
- pyxcp/recorder/setup.py +11 -10
- pyxcp/recorder/test_reko.py +2 -3
- pyxcp/recorder/unfolder.hpp +1332 -0
- pyxcp/recorder/wrap.cpp +171 -9
- pyxcp/recorder/writer.hpp +302 -0
- pyxcp/scripts/pyxcp_probe_can_drivers.py +0 -2
- pyxcp/scripts/xcp_examples.py +64 -0
- pyxcp/scripts/xcp_fetch_a2l.py +15 -10
- pyxcp/scripts/xcp_id_scanner.py +2 -6
- pyxcp/scripts/xcp_info.py +101 -63
- pyxcp/scripts/xcp_profile.py +27 -0
- pyxcp/stim/__init__.py +0 -0
- pyxcp/tests/test_asam_types.py +2 -2
- pyxcp/tests/test_binpacking.py +186 -0
- pyxcp/tests/test_can.py +1132 -38
- pyxcp/tests/test_checksum.py +2 -1
- pyxcp/tests/test_daq.py +193 -0
- pyxcp/tests/test_frame_padding.py +6 -3
- pyxcp/tests/test_master.py +42 -31
- pyxcp/tests/test_transport.py +12 -12
- pyxcp/tests/test_utils.py +2 -5
- pyxcp/timing.py +0 -2
- pyxcp/transport/__init__.py +9 -9
- pyxcp/transport/base.py +149 -127
- pyxcp/transport/base_transport.hpp +0 -0
- pyxcp/transport/can.py +194 -167
- pyxcp/transport/eth.py +80 -82
- pyxcp/transport/sxi.py +106 -60
- pyxcp/transport/transport_wrapper.cpp +0 -0
- pyxcp/transport/usb_transport.py +65 -83
- pyxcp/types.py +69 -20
- pyxcp/utils.py +47 -16
- pyxcp/vector/map.py +1 -3
- {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/METADATA +27 -22
- pyxcp-0.22.23.dist-info/RECORD +128 -0
- {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/WHEEL +1 -1
- {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/entry_points.txt +2 -0
- pyxcp/config.py +0 -57
- pyxcp/cxx/asynchiofactory.hpp +0 -24
- pyxcp/cxx/blocking_client.cpp +0 -44
- pyxcp/cxx/blocking_socket.cpp +0 -43
- pyxcp/cxx/blocking_socket.hpp +0 -558
- pyxcp/cxx/concurrent_queue.hpp +0 -60
- pyxcp/cxx/eth.hpp +0 -57
- pyxcp/cxx/exceptions.hpp +0 -30
- pyxcp/cxx/iasyncioservice.hpp +0 -31
- pyxcp/cxx/iresource.hpp +0 -17
- pyxcp/cxx/isocket.hpp +0 -22
- pyxcp/cxx/linux/epoll.cpp +0 -51
- pyxcp/cxx/linux/epoll.hpp +0 -87
- pyxcp/cxx/linux/lit_tester.cpp +0 -19
- pyxcp/cxx/linux/socket.hpp +0 -234
- pyxcp/cxx/linux/timeout.hpp +0 -81
- pyxcp/cxx/memoryblock.hpp +0 -42
- pyxcp/cxx/pool.hpp +0 -81
- pyxcp/cxx/poolmgr.cpp +0 -6
- pyxcp/cxx/poolmgr.hpp +0 -31
- pyxcp/cxx/test_queue.cpp +0 -69
- pyxcp/cxx/timestamp.hpp +0 -84
- pyxcp/cxx/utils.cpp +0 -38
- pyxcp/cxx/utils.hpp +0 -29
- pyxcp/cxx/win/iocp.cpp +0 -242
- pyxcp/cxx/win/iocp.hpp +0 -42
- pyxcp/cxx/win/perhandledata.hpp +0 -24
- pyxcp/cxx/win/periodata.hpp +0 -97
- pyxcp/cxx/win/socket.hpp +0 -185
- pyxcp/cxx/win/timeout.hpp +0 -83
- pyxcp/examples/conf_can.json +0 -20
- pyxcp/examples/conf_eth.json +0 -8
- pyxcp/logger.py +0 -67
- pyxcp/tests/test_config.py +0 -62
- pyxcp/transport/candriver/__init__.py +0 -2
- pyxcp/transport/candriver/pc_canalystii.py +0 -27
- pyxcp/transport/candriver/pc_etas.py +0 -25
- pyxcp/transport/candriver/pc_gsusb.py +0 -23
- pyxcp/transport/candriver/pc_iscan.py +0 -23
- pyxcp/transport/candriver/pc_ixxat.py +0 -27
- pyxcp/transport/candriver/pc_kvaser.py +0 -39
- pyxcp/transport/candriver/pc_neovi.py +0 -31
- pyxcp/transport/candriver/pc_nican.py +0 -23
- pyxcp/transport/candriver/pc_nixnet.py +0 -23
- pyxcp/transport/candriver/pc_pcan.py +0 -25
- pyxcp/transport/candriver/pc_seeed.py +0 -28
- pyxcp/transport/candriver/pc_serial.py +0 -27
- pyxcp/transport/candriver/pc_slcan.py +0 -29
- pyxcp/transport/candriver/pc_socketcan.py +0 -23
- pyxcp/transport/candriver/pc_systec.py +0 -29
- pyxcp/transport/candriver/pc_usb2can.py +0 -30
- pyxcp/transport/candriver/pc_vector.py +0 -34
- pyxcp/transport/candriver/python_can.py +0 -101
- pyxcp/transport/cxx_ext/CMakeLists.txt +0 -51
- pyxcp/transport/cxx_ext/setup.py +0 -49
- pyxcp/transport/cxx_ext/tests/test_basic_socket.cpp +0 -39
- pyxcp/transport/cxx_ext/tests/test_pool.cpp +0 -39
- pyxcp/transport/cxx_ext/tests/test_timestamp.cpp +0 -27
- pyxcp-0.21.9.dist-info/RECORD +0 -147
- rekorder.cp38-win_amd64.pyd +0 -0
- {pyxcp-0.21.9.dist-info/licenses → pyxcp-0.22.23.dist-info}/LICENSE +0 -0
pyxcp/recorder/rekorder.hpp
CHANGED
|
@@ -1,125 +1,124 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
2
|
#if !defined(__REKORDER_HPP)
|
|
4
|
-
#define __REKORDER_HPP
|
|
5
|
-
|
|
6
|
-
#if !defined(STANDALONE_REKORDER)
|
|
7
|
-
|
|
8
|
-
#endif /* STANDALONE_REKORDER */
|
|
9
|
-
|
|
10
|
-
#include <array>
|
|
11
|
-
#include <atomic>
|
|
12
|
-
#include <
|
|
13
|
-
#include <
|
|
14
|
-
#include <
|
|
15
|
-
#include <
|
|
16
|
-
#include <
|
|
17
|
-
#include <
|
|
18
|
-
#include <
|
|
19
|
-
#include <
|
|
20
|
-
#include <
|
|
21
|
-
#include <
|
|
22
|
-
|
|
23
|
-
#include <
|
|
24
|
-
#include <
|
|
25
|
-
#include <
|
|
26
|
-
#include <
|
|
27
|
-
#include <
|
|
28
|
-
|
|
29
|
-
#include <
|
|
30
|
-
#include <
|
|
31
|
-
#include <
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
#
|
|
35
|
-
#include
|
|
36
|
-
#include
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
#
|
|
46
|
-
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
#
|
|
55
|
-
|
|
56
|
-
#
|
|
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 =
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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::
|
|
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) ==
|
|
93
|
+
static_assert(sizeof(FileHeaderType) == 38);
|
|
94
94
|
|
|
95
|
-
struct ContainerHeaderType
|
|
96
|
-
|
|
97
|
-
uint32_t
|
|
98
|
-
uint32_t
|
|
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
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
using
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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::
|
|
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::
|
|
147
|
+
using rounding_func_t = std::function<std::uint64_t(std::uint64_t)>;
|
|
151
148
|
|
|
152
|
-
inline rounding_func_t create_rounding_func(std::
|
|
153
|
-
return [multiple](std::
|
|
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
|
-
|
|
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
|
-
|
|
170
|
-
|
|
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
|
-
|
|
200
|
-
|
|
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
|
-
|
|
181
|
+
return static_cast<blob_t*>(buf.ptr);
|
|
182
|
+
}
|
|
183
|
+
#endif /* STANDALONE_REKORDER */
|
|
313
184
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
-
|
|
386
|
-
auto payload= new char[length];
|
|
387
|
-
//auto payload = mem.acquire();
|
|
212
|
+
auto message = strerror(static_cast<int>(error_code.value()));
|
|
388
213
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
214
|
+
ss << "[ERROR] ";
|
|
215
|
+
ss << func << ": ";
|
|
216
|
+
ss << message;
|
|
217
|
+
return ss.str();
|
|
218
|
+
}
|
|
394
219
|
|
|
395
|
-
|
|
396
|
-
|
|
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
|
-
|
|
411
|
-
{
|
|
412
|
-
return (blob_t *)(m_mmap->data() + pos);
|
|
413
|
-
}
|
|
224
|
+
#endif // _WIN32
|
|
414
225
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
-
|
|
448
|
-
{
|
|
449
|
-
|
|
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
|
-
|
|
452
|
-
|
|
238
|
+
inline std::string& trim(std::string& s) {
|
|
239
|
+
return ltrim(rtrim(s));
|
|
240
|
+
}
|
|
453
241
|
|
|
454
|
-
|
|
455
|
-
|
|
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
|
-
|
|
469
|
-
|
|
470
|
-
|
|
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
|
-
|
|
501
|
-
|
|
502
|
-
|
|
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::
|
|
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
|
-
|
|
581
|
-
|
|
582
|
-
|
|
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
|
-
|
|
648
|
-
{
|
|
649
|
-
|
|
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
|
-
|
|
654
|
-
|
|
655
|
-
|
|
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
|
|
274
|
+
#endif // __REKORDER_HPP
|