pybase16384 0.3.9__cp312-cp312-musllinux_1_2_aarch64.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.
- pybase16384/__init__.py +205 -0
- pybase16384/backends/__init__.py +1 -0
- pybase16384/backends/cffi/__init__.py +463 -0
- pybase16384/backends/cffi/_core.abi3.so +0 -0
- pybase16384/backends/cffi/build.py +183 -0
- pybase16384/backends/cython/__init__.py +36 -0
- pybase16384/backends/cython/_core.abi3.so +0 -0
- pybase16384/backends/cython/_core.c +39928 -0
- pybase16384/backends/cython/_core.pxi +12 -0
- pybase16384/backends/cython/_core.pyx +619 -0
- pybase16384/backends/cython/base16384.pxd +113 -0
- pybase16384-0.3.9.dist-info/METADATA +216 -0
- pybase16384-0.3.9.dist-info/RECORD +16 -0
- pybase16384-0.3.9.dist-info/WHEEL +5 -0
- pybase16384-0.3.9.dist-info/licenses/LICENSE +674 -0
- pybase16384-0.3.9.dist-info/top_level.txt +1 -0
pybase16384/__init__.py
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import platform
|
|
3
|
+
from io import BytesIO
|
|
4
|
+
|
|
5
|
+
impl = platform.python_implementation()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _should_use_cffi() -> bool:
|
|
9
|
+
ev = os.getenv("B14_USE_CFFI")
|
|
10
|
+
if ev is not None:
|
|
11
|
+
return True
|
|
12
|
+
if impl == "CPython":
|
|
13
|
+
return False
|
|
14
|
+
else:
|
|
15
|
+
return True
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if not _should_use_cffi():
|
|
19
|
+
from pybase16384.backends.cython import (
|
|
20
|
+
DECBUFSZ,
|
|
21
|
+
ENCBUFSZ,
|
|
22
|
+
FLAG_DO_SUM_CHECK_FORCELY,
|
|
23
|
+
FLAG_NOHEADER,
|
|
24
|
+
FLAG_SUM_CHECK_ON_REMAIN,
|
|
25
|
+
_decode,
|
|
26
|
+
_decode_into,
|
|
27
|
+
_decode_into_safe,
|
|
28
|
+
_decode_safe,
|
|
29
|
+
_encode,
|
|
30
|
+
_encode_into,
|
|
31
|
+
_encode_into_safe,
|
|
32
|
+
_encode_safe,
|
|
33
|
+
decode_fd,
|
|
34
|
+
decode_fd_detailed,
|
|
35
|
+
decode_file,
|
|
36
|
+
decode_file_safe,
|
|
37
|
+
decode_len,
|
|
38
|
+
decode_local_file,
|
|
39
|
+
decode_local_file_detailed,
|
|
40
|
+
decode_stream_detailed,
|
|
41
|
+
encode_fd,
|
|
42
|
+
encode_fd_detailed,
|
|
43
|
+
encode_file,
|
|
44
|
+
encode_file_safe,
|
|
45
|
+
encode_len,
|
|
46
|
+
encode_local_file,
|
|
47
|
+
encode_local_file_detailed,
|
|
48
|
+
encode_stream_detailed,
|
|
49
|
+
is_64bits,
|
|
50
|
+
)
|
|
51
|
+
else:
|
|
52
|
+
from pybase16384.backends.cffi import (
|
|
53
|
+
DECBUFSZ,
|
|
54
|
+
ENCBUFSZ,
|
|
55
|
+
FLAG_DO_SUM_CHECK_FORCELY,
|
|
56
|
+
FLAG_NOHEADER,
|
|
57
|
+
FLAG_SUM_CHECK_ON_REMAIN,
|
|
58
|
+
_decode,
|
|
59
|
+
_decode_into,
|
|
60
|
+
_decode_into_safe,
|
|
61
|
+
_decode_safe,
|
|
62
|
+
_encode,
|
|
63
|
+
_encode_into,
|
|
64
|
+
_encode_into_safe,
|
|
65
|
+
_encode_safe,
|
|
66
|
+
decode_fd,
|
|
67
|
+
decode_fd_detailed,
|
|
68
|
+
decode_file,
|
|
69
|
+
decode_file_safe,
|
|
70
|
+
decode_len,
|
|
71
|
+
decode_local_file,
|
|
72
|
+
decode_local_file_detailed,
|
|
73
|
+
decode_stream_detailed,
|
|
74
|
+
encode_fd,
|
|
75
|
+
encode_fd_detailed,
|
|
76
|
+
encode_file,
|
|
77
|
+
encode_file_safe,
|
|
78
|
+
encode_len,
|
|
79
|
+
encode_local_file,
|
|
80
|
+
encode_local_file_detailed,
|
|
81
|
+
encode_stream_detailed,
|
|
82
|
+
is_64bits,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
__version__ = "0.3.9"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def encode(data: bytes) -> bytes:
|
|
89
|
+
inp = BytesIO(data)
|
|
90
|
+
out = BytesIO()
|
|
91
|
+
encode_file(inp, out, False, len(data) // 7)
|
|
92
|
+
return out.getvalue()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def encode_safe(data: bytes) -> bytes:
|
|
96
|
+
inp = BytesIO(data)
|
|
97
|
+
out = BytesIO()
|
|
98
|
+
encode_file_safe(inp, out, False, len(data) // 7)
|
|
99
|
+
return out.getvalue()
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def decode(data: bytes) -> bytes:
|
|
103
|
+
inp = BytesIO(data)
|
|
104
|
+
out = BytesIO()
|
|
105
|
+
decode_file(inp, out, len(data) // 8)
|
|
106
|
+
return out.getvalue()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def decode_safe(data: bytes) -> bytes:
|
|
110
|
+
inp = BytesIO(data)
|
|
111
|
+
out = BytesIO()
|
|
112
|
+
decode_file_safe(inp, out, len(data) // 8)
|
|
113
|
+
return out.getvalue()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def encode_from_string(data: str, write_head: bool = False) -> bytes:
|
|
117
|
+
bt = data.encode()
|
|
118
|
+
inp = BytesIO(bt)
|
|
119
|
+
out = BytesIO()
|
|
120
|
+
encode_file(inp, out, write_head, len(bt) // 7)
|
|
121
|
+
return out.getvalue()
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def encode_from_string_safe(data: str, write_head: bool = False) -> bytes:
|
|
125
|
+
bt = data.encode()
|
|
126
|
+
inp = BytesIO(bt)
|
|
127
|
+
out = BytesIO()
|
|
128
|
+
encode_file_safe(inp, out, write_head, len(bt) // 7)
|
|
129
|
+
return out.getvalue()
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def encode_to_string(data: bytes) -> str:
|
|
133
|
+
inp = BytesIO(data)
|
|
134
|
+
out = BytesIO()
|
|
135
|
+
encode_file(inp, out, False, len(data) // 7)
|
|
136
|
+
return out.getvalue().decode("utf-16-be")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def encode_to_string_safe(data: bytes) -> str:
|
|
140
|
+
inp = BytesIO(data)
|
|
141
|
+
out = BytesIO()
|
|
142
|
+
encode_file_safe(inp, out, False, len(data) // 7)
|
|
143
|
+
return out.getvalue().decode("utf-16-be")
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def encode_string(data: str) -> str:
|
|
147
|
+
data = data.encode()
|
|
148
|
+
inp = BytesIO(data)
|
|
149
|
+
out = BytesIO()
|
|
150
|
+
encode_file(inp, out, False, len(data) // 7)
|
|
151
|
+
return out.getvalue().decode("utf-16-be")
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def encode_string_safe(data: str) -> str:
|
|
155
|
+
data = data.encode()
|
|
156
|
+
inp = BytesIO(data)
|
|
157
|
+
out = BytesIO()
|
|
158
|
+
encode_file_safe(inp, out, False, len(data) // 7)
|
|
159
|
+
return out.getvalue().decode("utf-16-be")
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def decode_from_bytes(data: bytes) -> str:
|
|
163
|
+
inp = BytesIO(data)
|
|
164
|
+
out = BytesIO()
|
|
165
|
+
decode_file(inp, out, len(data) // 8)
|
|
166
|
+
return out.getvalue().decode()
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def decode_from_bytes_safe(data: bytes) -> str:
|
|
170
|
+
inp = BytesIO(data)
|
|
171
|
+
out = BytesIO()
|
|
172
|
+
decode_file_safe(inp, out, len(data) // 8)
|
|
173
|
+
return out.getvalue().decode()
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def decode_from_string(data: str) -> bytes:
|
|
177
|
+
bt = data.encode("utf-16-be")
|
|
178
|
+
inp = BytesIO(bt)
|
|
179
|
+
out = BytesIO()
|
|
180
|
+
decode_file(inp, out, len(bt) // 8)
|
|
181
|
+
return out.getvalue()
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def decode_from_string_safe(data: str) -> bytes:
|
|
185
|
+
bt = data.encode("utf-16-be")
|
|
186
|
+
inp = BytesIO(bt)
|
|
187
|
+
out = BytesIO()
|
|
188
|
+
decode_file_safe(inp, out, len(bt) // 8)
|
|
189
|
+
return out.getvalue()
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def decode_string(data: str) -> str:
|
|
193
|
+
bt = data.encode("utf-16-be")
|
|
194
|
+
inp = BytesIO(bt)
|
|
195
|
+
out = BytesIO()
|
|
196
|
+
decode_file(inp, out, len(bt) // 8)
|
|
197
|
+
return out.getvalue().decode()
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def decode_string_safe(data: str) -> str:
|
|
201
|
+
bt = data.encode("utf-16-be")
|
|
202
|
+
inp = BytesIO(bt)
|
|
203
|
+
out = BytesIO()
|
|
204
|
+
decode_file_safe(inp, out, len(bt) // 8)
|
|
205
|
+
return out.getvalue().decode()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Make cython happy, otherwise couldn't find pxd files
|
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) 2008-2021 synodriver <synodriver@gmail.com>
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import IO
|
|
7
|
+
|
|
8
|
+
from pybase16384.backends.cffi._core import ffi, lib
|
|
9
|
+
|
|
10
|
+
__version__ = "0.1.0"
|
|
11
|
+
|
|
12
|
+
encode_len = lib.base16384_encode_len
|
|
13
|
+
decode_len = lib.base16384_decode_len
|
|
14
|
+
|
|
15
|
+
ENCBUFSZ = lib.get_encsize()
|
|
16
|
+
DECBUFSZ = lib.get_decsize()
|
|
17
|
+
FLAG_NOHEADER = lib.BASE16384_FLAG_NOHEADER_()
|
|
18
|
+
FLAG_SUM_CHECK_ON_REMAIN = lib.BASE16384_FLAG_SUM_CHECK_ON_REMAIN_()
|
|
19
|
+
FLAG_DO_SUM_CHECK_FORCELY = lib.BASE16384_FLAG_DO_SUM_CHECK_FORCELY_()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# -----------------low level api------------------------------
|
|
23
|
+
def _encode(data: bytes) -> bytes:
|
|
24
|
+
length = len(data)
|
|
25
|
+
output_size = encode_len(length) + 16
|
|
26
|
+
output_buf = ffi.new(f"char[{output_size}]")
|
|
27
|
+
if output_buf == ffi.NULL:
|
|
28
|
+
raise MemoryError
|
|
29
|
+
count = lib.base16384_encode(ffi.from_buffer(data), length, output_buf)
|
|
30
|
+
return ffi.unpack(output_buf, count)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _encode_safe(data: bytes) -> bytes:
|
|
34
|
+
length = len(data)
|
|
35
|
+
output_size = encode_len(length)
|
|
36
|
+
output_buf = ffi.new(f"char[{output_size}]")
|
|
37
|
+
if output_buf == ffi.NULL:
|
|
38
|
+
raise MemoryError
|
|
39
|
+
count = lib.base16384_encode_safe(ffi.from_buffer(data), length, output_buf)
|
|
40
|
+
return ffi.unpack(output_buf, count)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _encode_into(data: bytes, out: bytearray) -> int:
|
|
44
|
+
return lib.base16384_encode(ffi.from_buffer(data), len(data), ffi.from_buffer(out))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _encode_into_safe(data: bytes, out: bytearray) -> int:
|
|
48
|
+
return lib.base16384_encode_safe(
|
|
49
|
+
ffi.from_buffer(data), len(data), ffi.from_buffer(out)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _decode(data: bytes) -> bytes:
|
|
54
|
+
length = len(data)
|
|
55
|
+
output_size = decode_len(length, 0) + 16
|
|
56
|
+
output_buf = ffi.new(f"char[{output_size}]")
|
|
57
|
+
if output_buf == ffi.NULL:
|
|
58
|
+
raise MemoryError
|
|
59
|
+
count = lib.base16384_decode(ffi.from_buffer(data), length, output_buf)
|
|
60
|
+
return ffi.unpack(output_buf, count)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _decode_safe(data: bytes) -> bytes:
|
|
64
|
+
length = len(data)
|
|
65
|
+
output_size = decode_len(length, 0)
|
|
66
|
+
output_buf = ffi.new(f"char[{output_size}]")
|
|
67
|
+
if output_buf == ffi.NULL:
|
|
68
|
+
raise MemoryError
|
|
69
|
+
count = lib.base16384_decode_safe(ffi.from_buffer(data), length, output_buf)
|
|
70
|
+
return ffi.unpack(output_buf, count)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _decode_into(data: bytes, out: bytearray) -> int:
|
|
74
|
+
return lib.base16384_decode(ffi.from_buffer(data), len(data), ffi.from_buffer(out))
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _decode_into_safe(data: bytes, out: bytearray) -> int:
|
|
78
|
+
return lib.base16384_decode_safe(
|
|
79
|
+
ffi.from_buffer(data), len(data), ffi.from_buffer(out)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def is_64bits() -> bool:
|
|
84
|
+
return bool(lib.pybase16384_64bits())
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# ----------------------------
|
|
88
|
+
def _check_file(file) -> bool:
|
|
89
|
+
if hasattr(file, "read") and hasattr(file, "write") and hasattr(file, "seek"):
|
|
90
|
+
return True
|
|
91
|
+
return False
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def encode_file(input: IO, output: IO, write_head: bool = False, buf_rate: int = 10):
|
|
95
|
+
if not _check_file(input):
|
|
96
|
+
raise TypeError(
|
|
97
|
+
"input except a file-like object, got %s" % type(input).__name__
|
|
98
|
+
)
|
|
99
|
+
if not _check_file(output):
|
|
100
|
+
raise TypeError(
|
|
101
|
+
"output except a file-like object, got %s" % type(input).__name__
|
|
102
|
+
)
|
|
103
|
+
if buf_rate <= 0:
|
|
104
|
+
buf_rate = 1
|
|
105
|
+
if write_head:
|
|
106
|
+
output.write(b"\xfe\xff")
|
|
107
|
+
|
|
108
|
+
current_buf_len: int = buf_rate * 7 # 一次读取这么多字节
|
|
109
|
+
output_size: int = (
|
|
110
|
+
encode_len(current_buf_len) + 16
|
|
111
|
+
) # 因为encode_len不是单调的 这16备用
|
|
112
|
+
output_buf = ffi.new(f"char[{output_size}]")
|
|
113
|
+
if output_buf == ffi.NULL:
|
|
114
|
+
raise MemoryError
|
|
115
|
+
first_check: int = (
|
|
116
|
+
1 # 检查一次就行了 怎么可能出现第一次读出来是bytes 以后又变卦了的对象呢 不会吧不会吧
|
|
117
|
+
)
|
|
118
|
+
while True:
|
|
119
|
+
chunk = input.read(current_buf_len)
|
|
120
|
+
if first_check:
|
|
121
|
+
first_check = 0
|
|
122
|
+
if not isinstance(chunk, bytes):
|
|
123
|
+
raise TypeError(
|
|
124
|
+
f"input must be a file-like rb object, got {type(input).__name__}"
|
|
125
|
+
)
|
|
126
|
+
size = len(chunk)
|
|
127
|
+
if size < current_buf_len: # 数据不够了 要减小一次读取的量
|
|
128
|
+
if (
|
|
129
|
+
buf_rate > 1
|
|
130
|
+
): # 重新设置一次读取的大小 重新设置流的位置 当然要是已经是一次读取7字节了 那就不能再变小了 直接encode吧
|
|
131
|
+
buf_rate = buf_rate // 2
|
|
132
|
+
current_buf_len = buf_rate * 7
|
|
133
|
+
input.seek(-size, 1)
|
|
134
|
+
continue
|
|
135
|
+
|
|
136
|
+
count = lib.base16384_encode(ffi.from_buffer(chunk), size, output_buf)
|
|
137
|
+
output.write(ffi.unpack(output_buf, count))
|
|
138
|
+
if size < 7:
|
|
139
|
+
break
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def encode_file_safe(
|
|
143
|
+
input: IO, output: IO, write_head: bool = False, buf_rate: int = 10
|
|
144
|
+
):
|
|
145
|
+
if not _check_file(input):
|
|
146
|
+
raise TypeError(
|
|
147
|
+
"input except a file-like object, got %s" % type(input).__name__
|
|
148
|
+
)
|
|
149
|
+
if not _check_file(output):
|
|
150
|
+
raise TypeError(
|
|
151
|
+
"output except a file-like object, got %s" % type(input).__name__
|
|
152
|
+
)
|
|
153
|
+
if buf_rate <= 0:
|
|
154
|
+
buf_rate = 1
|
|
155
|
+
if write_head:
|
|
156
|
+
output.write(b"\xfe\xff")
|
|
157
|
+
|
|
158
|
+
current_buf_len: int = buf_rate * 7 # 一次读取这么多字节
|
|
159
|
+
output_size: int = encode_len(
|
|
160
|
+
current_buf_len
|
|
161
|
+
) # 因为encode_len不是单调的 safe不用加16
|
|
162
|
+
output_buf = ffi.new(f"char[{output_size}]")
|
|
163
|
+
if output_buf == ffi.NULL:
|
|
164
|
+
raise MemoryError
|
|
165
|
+
first_check: int = (
|
|
166
|
+
1 # 检查一次就行了 怎么可能出现第一次读出来是bytes 以后又变卦了的对象呢 不会吧不会吧
|
|
167
|
+
)
|
|
168
|
+
while True:
|
|
169
|
+
chunk = input.read(current_buf_len)
|
|
170
|
+
if first_check:
|
|
171
|
+
first_check = 0
|
|
172
|
+
if not isinstance(chunk, bytes):
|
|
173
|
+
raise TypeError(
|
|
174
|
+
f"input must be a file-like rb object, got {type(input).__name__}"
|
|
175
|
+
)
|
|
176
|
+
size = len(chunk)
|
|
177
|
+
if size < current_buf_len: # 数据不够了 要减小一次读取的量
|
|
178
|
+
if (
|
|
179
|
+
buf_rate > 1
|
|
180
|
+
): # 重新设置一次读取的大小 重新设置流的位置 当然要是已经是一次读取7字节了 那就不能再变小了 直接encode吧
|
|
181
|
+
buf_rate = buf_rate // 2
|
|
182
|
+
current_buf_len = buf_rate * 7
|
|
183
|
+
input.seek(-size, 1)
|
|
184
|
+
continue
|
|
185
|
+
|
|
186
|
+
count = lib.base16384_encode_safe(ffi.from_buffer(chunk), size, output_buf)
|
|
187
|
+
output.write(ffi.unpack(output_buf, count))
|
|
188
|
+
if size < 7:
|
|
189
|
+
break
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def decode_file(input: IO, output: IO, buf_rate: int = 10):
|
|
193
|
+
if not _check_file(input):
|
|
194
|
+
raise TypeError(
|
|
195
|
+
"input except a file-like object, got %s" % type(input).__name__
|
|
196
|
+
)
|
|
197
|
+
if not _check_file(output):
|
|
198
|
+
raise TypeError(
|
|
199
|
+
"output except a file-like object, got %s" % type(output).__name__
|
|
200
|
+
)
|
|
201
|
+
if buf_rate <= 0:
|
|
202
|
+
buf_rate = 1
|
|
203
|
+
|
|
204
|
+
chunk = input.read(1) # type: bytes
|
|
205
|
+
if not isinstance(chunk, bytes):
|
|
206
|
+
raise TypeError(
|
|
207
|
+
f"input must be a file-like rb object, got {type(input).__name__}"
|
|
208
|
+
)
|
|
209
|
+
if chunk == b"\xfe": # 去头
|
|
210
|
+
input.read(1)
|
|
211
|
+
else:
|
|
212
|
+
input.seek(0, 0) # 没有头 回到开头
|
|
213
|
+
|
|
214
|
+
current_buf_len: int = buf_rate * 8
|
|
215
|
+
output_size: int = decode_len(current_buf_len, 0) + 16
|
|
216
|
+
output_buf = ffi.new(f"char[{output_size}]")
|
|
217
|
+
if output_buf == ffi.NULL:
|
|
218
|
+
raise MemoryError
|
|
219
|
+
while True:
|
|
220
|
+
chunk = input.read(current_buf_len) # 8的倍数
|
|
221
|
+
size = len(chunk)
|
|
222
|
+
if size == 0:
|
|
223
|
+
break
|
|
224
|
+
if size < current_buf_len: # 长度不够了
|
|
225
|
+
if buf_rate > 1: # 还能继续变小
|
|
226
|
+
buf_rate = buf_rate // 2 # 重新设置一次读取的大小
|
|
227
|
+
current_buf_len = buf_rate * 8
|
|
228
|
+
input.seek(-size, 1)
|
|
229
|
+
continue
|
|
230
|
+
tmp = input.read(2) # type: bytes
|
|
231
|
+
if len(tmp) == 2:
|
|
232
|
+
if tmp[0] == 61: # = stream完了 一次解码8n+2个字节
|
|
233
|
+
chunk += tmp
|
|
234
|
+
size += 2
|
|
235
|
+
else:
|
|
236
|
+
input.seek(-2, 1)
|
|
237
|
+
|
|
238
|
+
count = lib.base16384_decode(ffi.from_buffer(chunk), size, output_buf)
|
|
239
|
+
output.write(ffi.unpack(output_buf, count))
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def decode_file_safe(input: IO, output: IO, buf_rate: int = 10):
|
|
243
|
+
if not _check_file(input):
|
|
244
|
+
raise TypeError(
|
|
245
|
+
"input except a file-like object, got %s" % type(input).__name__
|
|
246
|
+
)
|
|
247
|
+
if not _check_file(output):
|
|
248
|
+
raise TypeError(
|
|
249
|
+
"output except a file-like object, got %s" % type(output).__name__
|
|
250
|
+
)
|
|
251
|
+
if buf_rate <= 0:
|
|
252
|
+
buf_rate = 1
|
|
253
|
+
|
|
254
|
+
chunk = input.read(1) # type: bytes
|
|
255
|
+
if not isinstance(chunk, bytes):
|
|
256
|
+
raise TypeError(
|
|
257
|
+
f"input must be a file-like rb object, got {type(input).__name__}"
|
|
258
|
+
)
|
|
259
|
+
if chunk == b"\xfe": # 去头
|
|
260
|
+
input.read(1)
|
|
261
|
+
else:
|
|
262
|
+
input.seek(0, 0) # 没有头 回到开头
|
|
263
|
+
|
|
264
|
+
current_buf_len: int = buf_rate * 8
|
|
265
|
+
output_size: int = decode_len(current_buf_len, 0)
|
|
266
|
+
output_buf = ffi.new(f"char[{output_size}]")
|
|
267
|
+
if output_buf == ffi.NULL:
|
|
268
|
+
raise MemoryError
|
|
269
|
+
while True:
|
|
270
|
+
chunk = input.read(current_buf_len) # 8的倍数
|
|
271
|
+
size = len(chunk)
|
|
272
|
+
if size == 0:
|
|
273
|
+
break
|
|
274
|
+
if size < current_buf_len: # 长度不够了
|
|
275
|
+
if buf_rate > 1: # 还能继续变小
|
|
276
|
+
buf_rate = buf_rate // 2 # 重新设置一次读取的大小
|
|
277
|
+
current_buf_len = buf_rate * 8
|
|
278
|
+
input.seek(-size, 1)
|
|
279
|
+
continue
|
|
280
|
+
tmp = input.read(2) # type: bytes
|
|
281
|
+
if len(tmp) == 2:
|
|
282
|
+
if tmp[0] == 61: # = stream完了 一次解码8n+2个字节
|
|
283
|
+
chunk += tmp
|
|
284
|
+
size += 2
|
|
285
|
+
else:
|
|
286
|
+
input.seek(-2, 1)
|
|
287
|
+
|
|
288
|
+
count = lib.base16384_decode_safe(ffi.from_buffer(chunk), size, output_buf)
|
|
289
|
+
output.write(ffi.unpack(output_buf, count))
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def ensure_bytes(inp) -> bytes:
|
|
293
|
+
if isinstance(inp, str):
|
|
294
|
+
return inp.encode()
|
|
295
|
+
elif isinstance(inp, bytes):
|
|
296
|
+
return inp
|
|
297
|
+
elif isinstance(inp, Path):
|
|
298
|
+
return str(inp).encode()
|
|
299
|
+
else:
|
|
300
|
+
return bytes(inp)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def err_to_str(ret) -> str:
|
|
304
|
+
if ret == lib.base16384_err_get_file_size:
|
|
305
|
+
return "base16384_err_get_file_size"
|
|
306
|
+
elif ret == lib.base16384_err_fopen_output_file:
|
|
307
|
+
return "base16384_err_fopen_output_file"
|
|
308
|
+
elif ret == lib.base16384_err_fopen_input_file:
|
|
309
|
+
return "base16384_err_fopen_input_file"
|
|
310
|
+
elif ret == lib.base16384_err_write_file:
|
|
311
|
+
return "base16384_err_write_file"
|
|
312
|
+
elif ret == lib.base16384_err_open_input_file:
|
|
313
|
+
return "base16384_err_open_input_file"
|
|
314
|
+
elif ret == lib.base16384_err_map_input_file:
|
|
315
|
+
return "base16384_err_map_input_file"
|
|
316
|
+
elif ret == lib.base16384_err_read_file:
|
|
317
|
+
return "base16384_err_read_file"
|
|
318
|
+
elif ret == lib.base16384_err_invalid_file_name:
|
|
319
|
+
return "base16384_err_invalid_file_name"
|
|
320
|
+
elif ret == lib.base16384_err_invalid_file_name:
|
|
321
|
+
return "base16384_err_invalid_file_name"
|
|
322
|
+
elif ret == lib.base16384_err_invalid_commandline_parameter:
|
|
323
|
+
return "base16384_err_invalid_commandline_parameter"
|
|
324
|
+
elif ret == lib.base16384_err_invalid_decoding_checksum:
|
|
325
|
+
return "base16384_err_invalid_decoding_checksum"
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def encode_local_file(inp, out) -> None:
|
|
329
|
+
inp_name: bytes = ensure_bytes(inp)
|
|
330
|
+
out_name: bytes = ensure_bytes(out)
|
|
331
|
+
encbuf = ffi.new(f"char[{ENCBUFSZ}]")
|
|
332
|
+
decbuf = ffi.new(f"char[{DECBUFSZ}]")
|
|
333
|
+
ret = lib.base16384_encode_file(
|
|
334
|
+
ffi.from_buffer(inp_name), ffi.from_buffer(out_name), encbuf, decbuf
|
|
335
|
+
)
|
|
336
|
+
if ret != lib.base16384_err_ok:
|
|
337
|
+
raise ValueError(err_to_str(ret))
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def decode_local_file(inp, out) -> None:
|
|
341
|
+
inp_name: bytes = ensure_bytes(inp)
|
|
342
|
+
out_name: bytes = ensure_bytes(out)
|
|
343
|
+
encbuf = ffi.new(f"char[{ENCBUFSZ}]")
|
|
344
|
+
decbuf = ffi.new(f"char[{DECBUFSZ}]")
|
|
345
|
+
ret = lib.base16384_decode_file(
|
|
346
|
+
ffi.from_buffer(inp_name), ffi.from_buffer(out_name), encbuf, decbuf
|
|
347
|
+
)
|
|
348
|
+
if ret != lib.base16384_err_ok:
|
|
349
|
+
raise ValueError(err_to_str(ret))
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def encode_fd(inp: int, out: int) -> None:
|
|
353
|
+
encbuf = ffi.new(f"char[{ENCBUFSZ}]")
|
|
354
|
+
decbuf = ffi.new(f"char[{DECBUFSZ}]")
|
|
355
|
+
ret = lib.base16384_encode_fd(inp, out, encbuf, decbuf)
|
|
356
|
+
if ret != lib.base16384_err_ok:
|
|
357
|
+
raise ValueError(err_to_str(ret))
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def decode_fd(inp: int, out: int) -> None:
|
|
361
|
+
encbuf = ffi.new(f"char[{ENCBUFSZ}]")
|
|
362
|
+
decbuf = ffi.new(f"char[{DECBUFSZ}]")
|
|
363
|
+
ret = lib.base16384_decode_fd(inp, out, encbuf, decbuf)
|
|
364
|
+
if ret != lib.base16384_err_ok:
|
|
365
|
+
raise ValueError(err_to_str(ret))
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# detail
|
|
369
|
+
def encode_local_file_detailed(inp, out, flag: int) -> None:
|
|
370
|
+
inp_name: bytes = ensure_bytes(inp)
|
|
371
|
+
out_name: bytes = ensure_bytes(out)
|
|
372
|
+
encbuf = ffi.new(f"char[{ENCBUFSZ}]")
|
|
373
|
+
decbuf = ffi.new(f"char[{DECBUFSZ}]")
|
|
374
|
+
ret = lib.base16384_encode_file_detailed(
|
|
375
|
+
ffi.from_buffer(inp_name), ffi.from_buffer(out_name), encbuf, decbuf, flag
|
|
376
|
+
)
|
|
377
|
+
if ret != lib.base16384_err_ok:
|
|
378
|
+
raise ValueError(err_to_str(ret))
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def decode_local_file_detailed(inp, out, flag: int) -> None:
|
|
382
|
+
inp_name: bytes = ensure_bytes(inp)
|
|
383
|
+
out_name: bytes = ensure_bytes(out)
|
|
384
|
+
encbuf = ffi.new(f"char[{ENCBUFSZ}]")
|
|
385
|
+
decbuf = ffi.new(f"char[{DECBUFSZ}]")
|
|
386
|
+
ret = lib.base16384_decode_file_detailed(
|
|
387
|
+
ffi.from_buffer(inp_name), ffi.from_buffer(out_name), encbuf, decbuf, flag
|
|
388
|
+
)
|
|
389
|
+
if ret != lib.base16384_err_ok:
|
|
390
|
+
raise ValueError(err_to_str(ret))
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def encode_fd_detailed(inp: int, out: int, flag: int) -> None:
|
|
394
|
+
encbuf = ffi.new(f"char[{ENCBUFSZ}]")
|
|
395
|
+
decbuf = ffi.new(f"char[{DECBUFSZ}]")
|
|
396
|
+
ret = lib.base16384_encode_fd_detailed(inp, out, encbuf, decbuf, flag)
|
|
397
|
+
if ret != lib.base16384_err_ok:
|
|
398
|
+
raise ValueError(err_to_str(ret))
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def decode_fd_detailed(inp: int, out: int, flag: int) -> None:
|
|
402
|
+
encbuf = ffi.new(f"char[{ENCBUFSZ}]")
|
|
403
|
+
decbuf = ffi.new(f"char[{DECBUFSZ}]")
|
|
404
|
+
ret = lib.base16384_decode_fd_detailed(inp, out, encbuf, decbuf, flag)
|
|
405
|
+
if ret != lib.base16384_err_ok:
|
|
406
|
+
raise ValueError(err_to_str(ret))
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
# stream
|
|
410
|
+
@ffi.def_extern()
|
|
411
|
+
def b14_readcallback(client_data, buffer, count: int):
|
|
412
|
+
file = ffi.from_handle(client_data)
|
|
413
|
+
data: bytes = file.read(count)
|
|
414
|
+
data_size: int = len(data)
|
|
415
|
+
ffi.memmove(buffer, data, data_size)
|
|
416
|
+
return data_size
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
@ffi.def_extern()
|
|
420
|
+
def b14_writecallback(client_data, buffer, count: int):
|
|
421
|
+
file = ffi.from_handle(client_data)
|
|
422
|
+
data: bytes = ffi.unpack(ffi.cast("char*", buffer), count)
|
|
423
|
+
return file.write(data)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
def encode_stream_detailed(inp, out, flag: int):
|
|
427
|
+
encbuf = ffi.new(f"char[{ENCBUFSZ}]")
|
|
428
|
+
decbuf = ffi.new(f"char[{DECBUFSZ}]")
|
|
429
|
+
|
|
430
|
+
inpstream = ffi.new(f"base16384_stream_t *")
|
|
431
|
+
inpstream.f.reader = lib.b14_readcallback
|
|
432
|
+
handle_inp = ffi.new_handle(inp)
|
|
433
|
+
inpstream.client_data = handle_inp
|
|
434
|
+
|
|
435
|
+
outstream = ffi.new(f"base16384_stream_t *")
|
|
436
|
+
outstream.f.writer = lib.b14_writecallback
|
|
437
|
+
handle_out = ffi.new_handle(out)
|
|
438
|
+
outstream.client_data = handle_out
|
|
439
|
+
ret = lib.base16384_encode_stream_detailed(
|
|
440
|
+
inpstream, outstream, encbuf, decbuf, flag
|
|
441
|
+
)
|
|
442
|
+
if ret != lib.base16384_err_ok:
|
|
443
|
+
raise ValueError(err_to_str(ret))
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def decode_stream_detailed(inp, out, flag: int):
|
|
447
|
+
encbuf = ffi.new(f"char[{ENCBUFSZ}]")
|
|
448
|
+
decbuf = ffi.new(f"char[{DECBUFSZ}]")
|
|
449
|
+
|
|
450
|
+
inpstream = ffi.new(f"base16384_stream_t *")
|
|
451
|
+
inpstream.f.reader = lib.b14_readcallback
|
|
452
|
+
handle_inp = ffi.new_handle(inp)
|
|
453
|
+
inpstream.client_data = handle_inp
|
|
454
|
+
|
|
455
|
+
outstream = ffi.new(f"base16384_stream_t *")
|
|
456
|
+
outstream.f.writer = lib.b14_writecallback
|
|
457
|
+
handle_out = ffi.new_handle(out)
|
|
458
|
+
outstream.client_data = handle_out
|
|
459
|
+
ret = lib.base16384_decode_stream_detailed(
|
|
460
|
+
inpstream, outstream, encbuf, decbuf, flag
|
|
461
|
+
)
|
|
462
|
+
if ret != lib.base16384_err_ok:
|
|
463
|
+
raise ValueError(err_to_str(ret))
|
|
Binary file
|