pyxcp 0.25.4__cp313-cp313-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.
- pyxcp/__init__.py +20 -0
- pyxcp/aml/EtasCANMonitoring.a2l +82 -0
- pyxcp/aml/EtasCANMonitoring.aml +67 -0
- pyxcp/aml/XCP_Common.aml +408 -0
- pyxcp/aml/XCPonCAN.aml +78 -0
- pyxcp/aml/XCPonEth.aml +33 -0
- pyxcp/aml/XCPonFlx.aml +113 -0
- pyxcp/aml/XCPonSxI.aml +66 -0
- pyxcp/aml/XCPonUSB.aml +106 -0
- pyxcp/aml/ifdata_CAN.a2l +20 -0
- pyxcp/aml/ifdata_Eth.a2l +11 -0
- pyxcp/aml/ifdata_Flx.a2l +94 -0
- pyxcp/aml/ifdata_SxI.a2l +13 -0
- pyxcp/aml/ifdata_USB.a2l +81 -0
- pyxcp/asam/__init__.py +0 -0
- pyxcp/asam/types.py +131 -0
- pyxcp/asamkeydll.c +116 -0
- pyxcp/asamkeydll.exe +0 -0
- pyxcp/asamkeydll.sh +2 -0
- pyxcp/checksum.py +732 -0
- pyxcp/cmdline.py +71 -0
- pyxcp/config/__init__.py +1257 -0
- pyxcp/config/legacy.py +120 -0
- pyxcp/constants.py +47 -0
- pyxcp/cpp_ext/__init__.py +0 -0
- pyxcp/cpp_ext/aligned_buffer.hpp +168 -0
- pyxcp/cpp_ext/bin.hpp +105 -0
- pyxcp/cpp_ext/blockmem.hpp +58 -0
- pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp312-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp313-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/daqlist.hpp +374 -0
- pyxcp/cpp_ext/event.hpp +67 -0
- pyxcp/cpp_ext/extension_wrapper.cpp +131 -0
- pyxcp/cpp_ext/framing.hpp +360 -0
- pyxcp/cpp_ext/helper.hpp +280 -0
- pyxcp/cpp_ext/mcobject.hpp +248 -0
- pyxcp/cpp_ext/sxi_framing.hpp +332 -0
- pyxcp/cpp_ext/tsqueue.hpp +46 -0
- pyxcp/daq_stim/__init__.py +291 -0
- pyxcp/daq_stim/optimize/__init__.py +67 -0
- pyxcp/daq_stim/optimize/binpacking.py +41 -0
- pyxcp/daq_stim/scheduler.cpp +62 -0
- pyxcp/daq_stim/scheduler.hpp +75 -0
- pyxcp/daq_stim/stim.cp310-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp311-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp312-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp313-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 +50 -0
- pyxcp/dllif.py +100 -0
- pyxcp/errormatrix.py +878 -0
- pyxcp/examples/conf_can.toml +19 -0
- pyxcp/examples/conf_can_user.toml +16 -0
- pyxcp/examples/conf_can_vector.json +11 -0
- pyxcp/examples/conf_can_vector.toml +11 -0
- pyxcp/examples/conf_eth.toml +9 -0
- pyxcp/examples/conf_nixnet.json +20 -0
- pyxcp/examples/conf_socket_can.toml +12 -0
- pyxcp/examples/run_daq.py +165 -0
- pyxcp/examples/xcp_policy.py +60 -0
- pyxcp/examples/xcp_read_benchmark.py +38 -0
- pyxcp/examples/xcp_skel.py +48 -0
- pyxcp/examples/xcp_unlock.py +36 -0
- pyxcp/examples/xcp_user_supplied_driver.py +43 -0
- pyxcp/examples/xcphello.py +65 -0
- pyxcp/examples/xcphello_recorder.py +107 -0
- pyxcp/master/__init__.py +10 -0
- pyxcp/master/errorhandler.py +677 -0
- pyxcp/master/master.py +2641 -0
- pyxcp/py.typed +0 -0
- pyxcp/recorder/.idea/.gitignore +8 -0
- pyxcp/recorder/.idea/misc.xml +4 -0
- pyxcp/recorder/.idea/modules.xml +8 -0
- pyxcp/recorder/.idea/recorder.iml +6 -0
- pyxcp/recorder/.idea/sonarlint/issuestore/3/8/3808afc69ac1edb9d760000a2f137335b1b99728 +7 -0
- pyxcp/recorder/.idea/sonarlint/issuestore/9/a/9a2aa4db38d3115ed60da621e012c0efc0172aae +0 -0
- pyxcp/recorder/.idea/sonarlint/issuestore/b/4/b49006702b459496a8e8c94ebe60947108361b91 +0 -0
- pyxcp/recorder/.idea/sonarlint/issuestore/index.pb +7 -0
- pyxcp/recorder/.idea/sonarlint/securityhotspotstore/3/8/3808afc69ac1edb9d760000a2f137335b1b99728 +0 -0
- pyxcp/recorder/.idea/sonarlint/securityhotspotstore/9/a/9a2aa4db38d3115ed60da621e012c0efc0172aae +0 -0
- pyxcp/recorder/.idea/sonarlint/securityhotspotstore/b/4/b49006702b459496a8e8c94ebe60947108361b91 +0 -0
- pyxcp/recorder/.idea/sonarlint/securityhotspotstore/index.pb +7 -0
- pyxcp/recorder/.idea/vcs.xml +10 -0
- pyxcp/recorder/__init__.py +96 -0
- pyxcp/recorder/build_clang.cmd +1 -0
- pyxcp/recorder/build_clang.sh +2 -0
- pyxcp/recorder/build_gcc.cmd +1 -0
- pyxcp/recorder/build_gcc.sh +2 -0
- pyxcp/recorder/build_gcc_arm.sh +2 -0
- pyxcp/recorder/converter/__init__.py +444 -0
- pyxcp/recorder/lz4.c +2829 -0
- pyxcp/recorder/lz4.h +879 -0
- pyxcp/recorder/lz4hc.c +2041 -0
- pyxcp/recorder/lz4hc.h +413 -0
- pyxcp/recorder/mio.hpp +1714 -0
- pyxcp/recorder/reader.hpp +138 -0
- pyxcp/recorder/reco.py +278 -0
- pyxcp/recorder/recorder.rst +0 -0
- pyxcp/recorder/rekorder.cp310-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp311-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp312-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp313-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cpp +59 -0
- pyxcp/recorder/rekorder.hpp +274 -0
- pyxcp/recorder/setup.py +41 -0
- pyxcp/recorder/test_reko.py +34 -0
- pyxcp/recorder/unfolder.hpp +1354 -0
- pyxcp/recorder/wrap.cpp +184 -0
- pyxcp/recorder/writer.hpp +302 -0
- pyxcp/scripts/__init__.py +0 -0
- pyxcp/scripts/pyxcp_probe_can_drivers.py +20 -0
- pyxcp/scripts/xcp_examples.py +64 -0
- pyxcp/scripts/xcp_fetch_a2l.py +40 -0
- pyxcp/scripts/xcp_id_scanner.py +18 -0
- pyxcp/scripts/xcp_info.py +159 -0
- pyxcp/scripts/xcp_profile.py +26 -0
- pyxcp/scripts/xmraw_converter.py +31 -0
- pyxcp/stim/__init__.py +0 -0
- pyxcp/tests/test_asam_types.py +24 -0
- pyxcp/tests/test_binpacking.py +186 -0
- pyxcp/tests/test_can.py +1324 -0
- pyxcp/tests/test_checksum.py +95 -0
- pyxcp/tests/test_daq.py +193 -0
- pyxcp/tests/test_daq_opt.py +426 -0
- pyxcp/tests/test_frame_padding.py +156 -0
- pyxcp/tests/test_framing.py +262 -0
- pyxcp/tests/test_master.py +2116 -0
- pyxcp/tests/test_transport.py +177 -0
- pyxcp/tests/test_utils.py +30 -0
- pyxcp/timing.py +60 -0
- pyxcp/transport/__init__.py +13 -0
- pyxcp/transport/base.py +484 -0
- pyxcp/transport/base_transport.hpp +0 -0
- pyxcp/transport/can.py +660 -0
- pyxcp/transport/eth.py +254 -0
- pyxcp/transport/hdf5_policy.py +129 -0
- pyxcp/transport/sxi.py +209 -0
- pyxcp/transport/transport_ext.cp310-win_amd64.pyd +0 -0
- pyxcp/transport/transport_ext.cp311-win_amd64.pyd +0 -0
- pyxcp/transport/transport_ext.cp312-win_amd64.pyd +0 -0
- pyxcp/transport/transport_ext.cp313-win_amd64.pyd +0 -0
- pyxcp/transport/transport_ext.hpp +214 -0
- pyxcp/transport/transport_wrapper.cpp +249 -0
- pyxcp/transport/usb_transport.py +229 -0
- pyxcp/types.py +987 -0
- pyxcp/utils/__init__.py +127 -0
- pyxcp/utils/cli.py +78 -0
- pyxcp/vector/__init__.py +0 -0
- pyxcp/vector/map.py +82 -0
- pyxcp-0.25.4.dist-info/METADATA +341 -0
- pyxcp-0.25.4.dist-info/RECORD +157 -0
- pyxcp-0.25.4.dist-info/WHEEL +4 -0
- pyxcp-0.25.4.dist-info/entry_points.txt +9 -0
- pyxcp-0.25.4.dist-info/licenses/LICENSE +165 -0
pyxcp/config/legacy.py
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
|
|
3
|
+
from traitlets.config import LoggingConfigurable
|
|
4
|
+
from traitlets.config.loader import Config
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
LEGACY_KEYWORDS = {
|
|
8
|
+
# General
|
|
9
|
+
"LOGLEVEL": "General.loglevel",
|
|
10
|
+
"DISABLE_ERROR_HANDLING": "General.disable_error_handling",
|
|
11
|
+
"SEED_N_KEY_DLL": "General.seed_n_key_dll",
|
|
12
|
+
"SEED_N_KEY_DLL_SAME_BIT_WIDTH": "General.seed_n_key_dll_same_bit_width",
|
|
13
|
+
"DISCONNECT_RESPONSE_OPTIONAL": "General.disconnect_response_optional",
|
|
14
|
+
# Transport
|
|
15
|
+
"TRANSPORT": "Transport.layer",
|
|
16
|
+
"CREATE_DAQ_TIMESTAMPS": "Transport.create_daq_timestamps",
|
|
17
|
+
"TIMEOUT": "Transport.timeout",
|
|
18
|
+
"ALIGNMENT": "Transport.alignment",
|
|
19
|
+
# Eth
|
|
20
|
+
"HOST": "Transport.Eth.host",
|
|
21
|
+
"PORT": "Transport.Eth.port",
|
|
22
|
+
"PROTOCOL": "Transport.Eth.protocol",
|
|
23
|
+
"IPV6": "Transport.Eth.ipv6",
|
|
24
|
+
"TCP_NODELAY": "Transport.Eth.tcp_nodelay",
|
|
25
|
+
# Usb
|
|
26
|
+
"SERIAL_NUMBER": "Transport.Usb.serial_number",
|
|
27
|
+
"CONFIGURATION_NUMBER": "Transport.Usb.configuration_number",
|
|
28
|
+
"INTERFACE_NUMBER": "Transport.Usb.interface_number",
|
|
29
|
+
"COMMAND_ENDPOINT_NUMBER": "Transport.Usb.out_ep_number",
|
|
30
|
+
"REPLY_ENDPOINT_NUMBER": "Transport.Usb.in_ep_number",
|
|
31
|
+
"VENDOR_ID": "Transport.Usb.vendor_id",
|
|
32
|
+
"PRODUCT_ID": "Transport.Usb.product_id",
|
|
33
|
+
"LIBRARY": "Transport.Usb.library",
|
|
34
|
+
# Can
|
|
35
|
+
"CAN_DRIVER": "Transport.Can.interface",
|
|
36
|
+
"CHANNEL": "Transport.Can.channel",
|
|
37
|
+
"MAX_DLC_REQUIRED": "Transport.Can.max_dlc_required",
|
|
38
|
+
# "MAX_CAN_FD_DLC": "Transport.Can.max_can_fd_dlc",
|
|
39
|
+
"PADDING_VALUE": "Transport.Can.padding_value",
|
|
40
|
+
"CAN_USE_DEFAULT_LISTENER": "Transport.Can.use_default_listener",
|
|
41
|
+
# Swap master and slave IDs. (s. https://github.com/christoph2/pyxcp/issues/130)
|
|
42
|
+
"CAN_ID_SLAVE": "Transport.Can.can_id_master",
|
|
43
|
+
"CAN_ID_MASTER": "Transport.Can.can_id_slave",
|
|
44
|
+
"CAN_ID_BROADCAST": "Transport.Can.can_id_broadcast",
|
|
45
|
+
"BITRATE": "Transport.Can.bitrate",
|
|
46
|
+
"RECEIVE_OWN_MESSAGES": "Transport.Can.receive_own_messages",
|
|
47
|
+
"POLL_INTERVAL": "Transport.Can.poll_interval",
|
|
48
|
+
"FD": "Transport.Can.fd",
|
|
49
|
+
"DATA_BITRATE": "Transport.Can.data_bitrate",
|
|
50
|
+
"ACCEPT_VIRTUAL": "Transport.Can.Kvaser.accept_virtual",
|
|
51
|
+
"SJW": "Transport.Can.sjw_abr",
|
|
52
|
+
"TSEG1": "Transport.Can.tseg1_abr",
|
|
53
|
+
"TSEG2": "Transport.Can.tseg2_abr",
|
|
54
|
+
"TTY_BAUDRATE": "Transport.Can.SlCan.ttyBaudrate",
|
|
55
|
+
"UNIQUE_HARDWARE_ID": "Transport.Can.Ixxat.unique_hardware_id",
|
|
56
|
+
"RX_FIFO_SIZE": "Transport.Can.Ixxat.rx_fifo_size",
|
|
57
|
+
"TX_FIFO_SIZE": "Transport.Can.Ixxat.tx_fifo_size",
|
|
58
|
+
"DRIVER_MODE": "Transport.Can.Kvaser.driver_mode",
|
|
59
|
+
"NO_SAMP": "Transport.Can.Kvaser.no_samp",
|
|
60
|
+
"SINGLE_HANDLE": "Transport.Can.Kvaser.single_handle",
|
|
61
|
+
"USE_SYSTEM_TIMESTAMP": "Transport.Can.Neovi.use_system_timestamp",
|
|
62
|
+
"OVERRIDE_LIBRARY_NAME": "Transport.Can.Neovi.override_library_name",
|
|
63
|
+
"BAUDRATE": "Transport.Can.Serial.baudrate",
|
|
64
|
+
"SLEEP_AFTER_OPEN": "Transport.Can.SlCan.sleep_after_open",
|
|
65
|
+
"DEVICE_NUMBER": "Transport.Can.Systec.device_number",
|
|
66
|
+
"RX_BUFFER_ENTRIES": "Transport.Can.Systec.rx_buffer_entries",
|
|
67
|
+
"TX_BUFFER_ENTRIES": "Transport.Can.Systec.tx_buffer_entries",
|
|
68
|
+
"FLAGS": "Transport.Can.Usb2Can.flags",
|
|
69
|
+
"APP_NAME": "Transport.Can.Vector.app_name",
|
|
70
|
+
"RX_QUEUE_SIZE": "Transport.Can.Vector.rx_queue_size",
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def nested_dict_update(d: dict, key: str, value) -> None:
|
|
75
|
+
root, *path, key = key.split(".")
|
|
76
|
+
sub_dict = d[root]
|
|
77
|
+
for part in path:
|
|
78
|
+
if part not in sub_dict:
|
|
79
|
+
sub_dict[part] = defaultdict(dict)
|
|
80
|
+
sub_dict = sub_dict[part]
|
|
81
|
+
sub_dict[key] = value
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def convert_config(legacy_config: dict, logger: LoggingConfigurable) -> Config:
|
|
85
|
+
interface_name = None
|
|
86
|
+
resolv = []
|
|
87
|
+
d = defaultdict(dict)
|
|
88
|
+
for key, value in legacy_config.items():
|
|
89
|
+
key = key.upper()
|
|
90
|
+
item = LEGACY_KEYWORDS.get(key)
|
|
91
|
+
if item is None:
|
|
92
|
+
logger.warning(f"Unknown keyword {key!r} in config file")
|
|
93
|
+
continue
|
|
94
|
+
if key == "CAN_DRIVER":
|
|
95
|
+
value = value.lower()
|
|
96
|
+
interface_name = value
|
|
97
|
+
if key in ("SERIAL", "LOG_ERRORS", "STATE", "RTSCTS"):
|
|
98
|
+
resolv.append((key, value))
|
|
99
|
+
else:
|
|
100
|
+
nested_dict_update(d=d, key=item, value=value)
|
|
101
|
+
for key, value in resolv:
|
|
102
|
+
if key == "SERIAL":
|
|
103
|
+
if interface_name == "neovi":
|
|
104
|
+
d["Transport.Can.Neovi.serial"] = value
|
|
105
|
+
elif interface_name == "vector":
|
|
106
|
+
d["Transport.Can.Vector.serial"] = value
|
|
107
|
+
elif key == "LOG_ERRORS":
|
|
108
|
+
if interface_name == "nican":
|
|
109
|
+
d["Transport.Can.NiCan.log_errors"] = value
|
|
110
|
+
elif key == "STATE":
|
|
111
|
+
if interface_name == "pcan":
|
|
112
|
+
d["Transport.Can.PCan.state"] = value
|
|
113
|
+
elif interface_name == "systec":
|
|
114
|
+
d["Transport.Can.Systec.state"] = value
|
|
115
|
+
elif key == "RTSCTS":
|
|
116
|
+
if interface_name == "serial":
|
|
117
|
+
d["Transport.Can.Serial.rtscts"] = value
|
|
118
|
+
elif interface_name == "slcan":
|
|
119
|
+
d["Transport.Can.SlCan.rtscts"] = value
|
|
120
|
+
return Config(d)
|
pyxcp/constants.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
import struct
|
|
3
|
+
from typing import Any, Callable
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
PackerType = Callable[[int], bytes]
|
|
7
|
+
UnpackerType = Callable[[bytes], tuple[Any, ...]]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def makeBytePacker(byteorder: str = "@") -> PackerType:
|
|
11
|
+
""""""
|
|
12
|
+
return struct.Struct(f"{byteorder}B").pack
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def makeByteUnpacker(byteorder: str = "@") -> UnpackerType:
|
|
16
|
+
""""""
|
|
17
|
+
return struct.Struct(f"{byteorder}B").unpack
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def makeWordPacker(byteorder: str = "@") -> PackerType:
|
|
21
|
+
""""""
|
|
22
|
+
return struct.Struct(f"{byteorder}H").pack
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def makeWordUnpacker(byteorder: str = "@") -> UnpackerType:
|
|
26
|
+
""""""
|
|
27
|
+
return struct.Struct(f"{byteorder}H").unpack
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def makeDWordPacker(byteorder: str = "@") -> PackerType:
|
|
31
|
+
""""""
|
|
32
|
+
return struct.Struct(f"{byteorder}I").pack
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def makeDWordUnpacker(byteorder: str = "@") -> UnpackerType:
|
|
36
|
+
""""""
|
|
37
|
+
return struct.Struct(f"{byteorder}I").unpack
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def makeDLongPacker(byteorder: str = "@") -> PackerType:
|
|
41
|
+
""""""
|
|
42
|
+
return struct.Struct(f"{byteorder}Q").pack
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def makeDLongUnpacker(byteorder: str = "@") -> UnpackerType:
|
|
46
|
+
""""""
|
|
47
|
+
return struct.Struct(f"{byteorder}Q").unpack
|
|
File without changes
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
|
|
2
|
+
#if !defined(__ALIGNED_BUFFER_HPP)
|
|
3
|
+
#define __ALIGNED_BUFFER_HPP
|
|
4
|
+
|
|
5
|
+
#include <variant>
|
|
6
|
+
|
|
7
|
+
#include <cstdint>
|
|
8
|
+
#include <cstdlib>
|
|
9
|
+
#include <vector>
|
|
10
|
+
#include <string_view>
|
|
11
|
+
#include <stdexcept>
|
|
12
|
+
#include <algorithm>
|
|
13
|
+
#include <cstring>
|
|
14
|
+
|
|
15
|
+
#include <pybind11/pybind11.h>
|
|
16
|
+
|
|
17
|
+
#if (defined(_WIN32) || defined(_WIN64)) && defined(_MSC_VER)
|
|
18
|
+
#include <malloc.h>
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
namespace py = pybind11;
|
|
22
|
+
|
|
23
|
+
class AlignedBuffer {
|
|
24
|
+
|
|
25
|
+
public:
|
|
26
|
+
|
|
27
|
+
AlignedBuffer(size_t size = 0xffff) : m_size(size), m_current_pos(0) {
|
|
28
|
+
m_buffer = nullptr;
|
|
29
|
+
// Create naturally aligned buffer.
|
|
30
|
+
constexpr std::size_t align = alignof(int);
|
|
31
|
+
// aligned_alloc requires size to be a multiple of alignment.
|
|
32
|
+
const std::size_t aligned_size = ((m_size + align - 1) / align) * align;
|
|
33
|
+
#if (defined(_WIN32) || defined(_WIN64)) && defined(_MSC_VER)
|
|
34
|
+
m_buffer = static_cast<uint8_t*>(::_aligned_malloc(aligned_size, align));
|
|
35
|
+
#else
|
|
36
|
+
m_buffer = static_cast<uint8_t*>(::aligned_alloc(align, aligned_size));
|
|
37
|
+
#endif
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
AlignedBuffer(const AlignedBuffer& other) = delete;
|
|
41
|
+
AlignedBuffer& operator=(const AlignedBuffer& other) = delete;
|
|
42
|
+
AlignedBuffer(AlignedBuffer&& other) = delete;
|
|
43
|
+
AlignedBuffer& operator=(AlignedBuffer&& other) = delete;
|
|
44
|
+
|
|
45
|
+
~AlignedBuffer() {
|
|
46
|
+
if (m_buffer) {
|
|
47
|
+
#if (defined(_WIN32) || defined(_WIN64)) && defined(_MSC_VER)
|
|
48
|
+
::_aligned_free(m_buffer);
|
|
49
|
+
#else
|
|
50
|
+
::free(m_buffer);
|
|
51
|
+
#endif
|
|
52
|
+
m_buffer = nullptr;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
void reset() noexcept {
|
|
57
|
+
m_current_pos = 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
std::size_t size() const noexcept {
|
|
61
|
+
return m_current_pos;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Get an element by index
|
|
65
|
+
uint8_t get(size_t index) const {
|
|
66
|
+
if (index >= size()) throw std::out_of_range("Index out of range");
|
|
67
|
+
return m_buffer[index];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
void append(uint8_t value) {
|
|
71
|
+
if ((m_current_pos + 1) > m_size) {
|
|
72
|
+
throw std::overflow_error("Buffer overflow");
|
|
73
|
+
}
|
|
74
|
+
m_buffer[m_current_pos] = value;
|
|
75
|
+
m_current_pos++;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Set an element by index
|
|
79
|
+
void set(size_t index, uint8_t value) {
|
|
80
|
+
if (index >= size()) throw std::out_of_range("Index out of range");
|
|
81
|
+
m_buffer[index] = value;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static std::string_view bytes_as_string_view(const py::bytes& data) {
|
|
85
|
+
char* buf = nullptr;
|
|
86
|
+
Py_ssize_t len = 0;
|
|
87
|
+
if (PyBytes_AsStringAndSize(data.ptr(), &buf, &len) != 0 || buf == nullptr || len < 0) {
|
|
88
|
+
return std::string_view{};
|
|
89
|
+
}
|
|
90
|
+
return std::string_view(buf, static_cast<std::size_t>(len));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
void extend(const py::bytes& values) {
|
|
95
|
+
auto data_view = bytes_as_string_view(values);
|
|
96
|
+
|
|
97
|
+
if ((data_view.size() + m_current_pos) > m_size) {
|
|
98
|
+
throw std::invalid_argument("Values vector is too large");
|
|
99
|
+
}
|
|
100
|
+
if (!data_view.empty()) {
|
|
101
|
+
std::memcpy(m_buffer + m_current_pos, data_view.data(), data_view.size());
|
|
102
|
+
m_current_pos += data_view.size();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
void extend(const std::vector<std::uint8_t>& values) {
|
|
107
|
+
if ((values.size() + m_current_pos) > m_size) {
|
|
108
|
+
throw std::invalid_argument("Values vector is too large");
|
|
109
|
+
}
|
|
110
|
+
if (!values.empty()) {
|
|
111
|
+
std::memcpy(m_buffer + m_current_pos, values.data(), values.size());
|
|
112
|
+
m_current_pos += values.size();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
std::variant<uint8_t, py::bytes> get_item(py::object index) const {
|
|
117
|
+
if (py::isinstance<py::slice>(index)) {
|
|
118
|
+
py::slice slice = index.cast<py::slice>();
|
|
119
|
+
size_t start, stop, step, length;
|
|
120
|
+
if (!slice.compute(size(), &start, &stop, &step, &length)) {
|
|
121
|
+
throw py::error_already_set();
|
|
122
|
+
}
|
|
123
|
+
return slice(start, stop, step);
|
|
124
|
+
} else if (py::isinstance<py::int_>(index)) {
|
|
125
|
+
Py_ssize_t idx = index.cast<Py_ssize_t>();
|
|
126
|
+
if (idx < 0) {
|
|
127
|
+
idx += static_cast<Py_ssize_t>(size());
|
|
128
|
+
}
|
|
129
|
+
if (idx < 0 || static_cast<std::size_t>(idx) >= size()) {
|
|
130
|
+
throw std::out_of_range("Index out of range");
|
|
131
|
+
}
|
|
132
|
+
return get(static_cast<std::size_t>(idx));
|
|
133
|
+
} else {
|
|
134
|
+
throw py::type_error("Invalid index type");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
py::bytes slice(size_t start, size_t stop, size_t step) const {
|
|
139
|
+
if (step == 0) {
|
|
140
|
+
throw std::invalid_argument("Step cannot be zero");
|
|
141
|
+
}
|
|
142
|
+
// Clamp indices to valid range
|
|
143
|
+
start = std::max(size_t(0), std::min(start, size_t(size())));
|
|
144
|
+
stop = std::max(size_t(0), std::min(stop, size_t(size())));
|
|
145
|
+
|
|
146
|
+
if (start >= stop) {
|
|
147
|
+
return py::bytes("");
|
|
148
|
+
}
|
|
149
|
+
if (step == 1) {
|
|
150
|
+
return py::bytes(reinterpret_cast<const char*>(m_buffer) + start, stop - start);
|
|
151
|
+
}
|
|
152
|
+
// General step handling (build result with stride)
|
|
153
|
+
std::string out;
|
|
154
|
+
out.reserve((stop - start + step - 1) / step);
|
|
155
|
+
for (size_t i = start; i < stop; i += step) {
|
|
156
|
+
out.push_back(static_cast<char>(m_buffer[i]));
|
|
157
|
+
}
|
|
158
|
+
return py::bytes(out);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private:
|
|
162
|
+
size_t m_size;
|
|
163
|
+
size_t m_current_pos;
|
|
164
|
+
uint8_t * m_buffer;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
#endif // __ALIGNED_BUFFER_HPP
|
pyxcp/cpp_ext/bin.hpp
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
|
|
2
|
+
#if !defined(__BIN_HPP)
|
|
3
|
+
#define __BIN_HPP
|
|
4
|
+
|
|
5
|
+
#include <cstdint>
|
|
6
|
+
#include <iostream>
|
|
7
|
+
#include <map>
|
|
8
|
+
#include <optional>
|
|
9
|
+
#include <string>
|
|
10
|
+
#include <vector>
|
|
11
|
+
|
|
12
|
+
#include "mcobject.hpp"
|
|
13
|
+
|
|
14
|
+
class Bin {
|
|
15
|
+
public:
|
|
16
|
+
|
|
17
|
+
Bin(std::uint16_t size) : m_size(size), m_residual_capacity(size) {
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
Bin(std::uint16_t size, uint16_t residual_capacity, const std::vector<McObject>& entries) :
|
|
21
|
+
m_size(size), m_residual_capacity(residual_capacity), m_entries(entries) {
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void append(const McObject& bin) {
|
|
25
|
+
m_entries.emplace_back(bin);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
void set_entries(std::vector<McObject>&& entries) {
|
|
29
|
+
m_entries = std::move(entries);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
std::uint16_t get_size() const {
|
|
33
|
+
return m_size;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void set_size(const std::uint16_t size) {
|
|
37
|
+
m_size = size;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
std::uint16_t get_residual_capacity() const {
|
|
41
|
+
return m_residual_capacity;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
void set_residual_capacity(const std::uint16_t residual_capacity) {
|
|
45
|
+
m_residual_capacity = residual_capacity;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const std::vector<McObject>& get_entries() const {
|
|
49
|
+
return m_entries;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
bool operator==(const Bin& other) const {
|
|
53
|
+
return (m_size == other.m_size) && (m_residual_capacity == other.m_residual_capacity) && (m_entries == other.m_entries);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
std::string dumps() const {
|
|
57
|
+
std::stringstream ss;
|
|
58
|
+
|
|
59
|
+
ss << to_binary(m_size);
|
|
60
|
+
ss << to_binary(m_residual_capacity);
|
|
61
|
+
|
|
62
|
+
std::size_t entries_size = m_entries.size();
|
|
63
|
+
ss << to_binary(entries_size);
|
|
64
|
+
for (const auto& entry : m_entries) {
|
|
65
|
+
ss << entry.dumps();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return ss.str();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private:
|
|
72
|
+
|
|
73
|
+
std::uint16_t m_size;
|
|
74
|
+
std::uint16_t m_residual_capacity;
|
|
75
|
+
std::vector<McObject> m_entries{};
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
std::string bin_entries_to_string(const std::vector<McObject>& entries);
|
|
79
|
+
|
|
80
|
+
std::string to_string(const Bin& obj) {
|
|
81
|
+
std::stringstream ss;
|
|
82
|
+
ss << "Bin(size=" << obj.get_size() << ", residual_capacity=" << obj.get_residual_capacity() << ", entries=["
|
|
83
|
+
<< bin_entries_to_string(obj.get_entries()) << "])";
|
|
84
|
+
return ss.str();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
std::string bin_entries_to_string(const std::vector<McObject>& entries) {
|
|
88
|
+
std::stringstream ss;
|
|
89
|
+
for (std::size_t i = 0; i < entries.size(); ++i) {
|
|
90
|
+
ss << to_string(entries[i]);
|
|
91
|
+
if (i + 1 < entries.size()) {
|
|
92
|
+
ss << ", ";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return ss.str();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#if 0
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def __len__(self) -> int:
|
|
102
|
+
return len(self.entries)
|
|
103
|
+
#endif
|
|
104
|
+
|
|
105
|
+
#endif // __BIN_HPP
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
|
|
2
|
+
#ifndef __BLOCKMEM_HPP
|
|
3
|
+
#define __BLOCKMEM_HPP
|
|
4
|
+
|
|
5
|
+
#include <array>
|
|
6
|
+
#include <cstdint>
|
|
7
|
+
#include <mutex>
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
*
|
|
11
|
+
* Super simplicistic block memory manager.
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
14
|
+
template<typename T, int _IS, int _NB>
|
|
15
|
+
class BlockMemory {
|
|
16
|
+
public:
|
|
17
|
+
|
|
18
|
+
using mem_block_t = std::array<T, _IS>;
|
|
19
|
+
|
|
20
|
+
constexpr explicit BlockMemory() noexcept : m_memory{ nullptr }, m_allocation_count{ 0 } {
|
|
21
|
+
m_memory = new T[_IS * _NB];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
~BlockMemory() noexcept {
|
|
25
|
+
if (m_memory) {
|
|
26
|
+
delete[] m_memory;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
BlockMemory(const BlockMemory&) = delete;
|
|
31
|
+
|
|
32
|
+
constexpr T* acquire() noexcept {
|
|
33
|
+
const std::scoped_lock lock(m_mtx);
|
|
34
|
+
|
|
35
|
+
if (m_allocation_count >= _NB) {
|
|
36
|
+
return nullptr;
|
|
37
|
+
}
|
|
38
|
+
T* ptr = reinterpret_cast<T*>(m_memory + (m_allocation_count * _IS));
|
|
39
|
+
m_allocation_count++;
|
|
40
|
+
return ptr;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
constexpr void release() noexcept {
|
|
44
|
+
const std::scoped_lock lock(m_mtx);
|
|
45
|
+
if (m_allocation_count == 0) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
m_allocation_count--;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private:
|
|
52
|
+
|
|
53
|
+
T* m_memory;
|
|
54
|
+
std::uint32_t m_allocation_count;
|
|
55
|
+
std::mutex m_mtx;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
#endif // __BLOCKMEM_HPP
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|