mirror of
https://github.com/python/cpython.git
synced 2026-05-06 12:49:07 -04:00
gh-145980: Add support for alternative alphabets in the binascii module (GH-145981)
* Add the alphabet parameter in functions b2a_base64(), a2b_base64(), b2a_base85(), and a2b_base85(). * And a number of "*_ALPHABET" constants. * Remove b2a_z85() and a2b_z85().
This commit is contained in:
+64
-36
@@ -48,12 +48,15 @@ The :mod:`!binascii` module defines the following functions:
|
||||
Added the *backtick* parameter.
|
||||
|
||||
|
||||
.. function:: a2b_base64(string, /, *, strict_mode=False)
|
||||
a2b_base64(string, /, *, strict_mode=True, ignorechars)
|
||||
.. function:: a2b_base64(string, /, *, alphabet=BASE64_ALPHABET, strict_mode=False)
|
||||
a2b_base64(string, /, *, ignorechars, alphabet=BASE64_ALPHABET, strict_mode=True)
|
||||
|
||||
Convert a block of base64 data back to binary and return the binary data. More
|
||||
than one line may be passed at a time.
|
||||
|
||||
Optional *alphabet* must be a :class:`bytes` object of length 64 which
|
||||
specifies an alternative alphabet.
|
||||
|
||||
If *ignorechars* is specified, it should be a :term:`bytes-like object`
|
||||
containing characters to ignore from the input when *strict_mode* is true.
|
||||
If *ignorechars* contains the pad character ``'='``, the pad characters
|
||||
@@ -76,10 +79,10 @@ The :mod:`!binascii` module defines the following functions:
|
||||
Added the *strict_mode* parameter.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Added the *ignorechars* parameter.
|
||||
Added the *alphabet* and *ignorechars* parameters.
|
||||
|
||||
|
||||
.. function:: b2a_base64(data, *, wrapcol=0, newline=True)
|
||||
.. function:: b2a_base64(data, *, alphabet=BASE64_ALPHABET, wrapcol=0, newline=True)
|
||||
|
||||
Convert binary data to a line(s) of ASCII characters in base64 coding,
|
||||
as specified in :rfc:`4648`.
|
||||
@@ -95,7 +98,7 @@ The :mod:`!binascii` module defines the following functions:
|
||||
Added the *newline* parameter.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Added the *wrapcol* parameter.
|
||||
Added the *alphabet* and *wrapcol* parameters.
|
||||
|
||||
|
||||
.. function:: a2b_ascii85(string, /, *, foldspaces=False, adobe=False, ignorechars=b"")
|
||||
@@ -148,7 +151,7 @@ The :mod:`!binascii` module defines the following functions:
|
||||
.. versionadded:: 3.15
|
||||
|
||||
|
||||
.. function:: a2b_base85(string, /)
|
||||
.. function:: a2b_base85(string, /, *, alphabet=BASE85_ALPHABET)
|
||||
|
||||
Convert Base85 data back to binary and return the binary data.
|
||||
More than one line may be passed at a time.
|
||||
@@ -158,49 +161,25 @@ The :mod:`!binascii` module defines the following functions:
|
||||
characters). Each group encodes 32 bits of binary data in the range from
|
||||
``0`` to ``2 ** 32 - 1``, inclusive.
|
||||
|
||||
Optional *alphabet* must be a :class:`bytes` object of length 85 which
|
||||
specifies an alternative alphabet.
|
||||
|
||||
Invalid Base85 data will raise :exc:`binascii.Error`.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
|
||||
.. function:: b2a_base85(data, /, *, pad=False)
|
||||
.. function:: b2a_base85(data, /, *, alphabet=BASE85_ALPHABET, pad=False)
|
||||
|
||||
Convert binary data to a line of ASCII characters in Base85 coding.
|
||||
The return value is the converted line.
|
||||
|
||||
If *pad* is true, the input is padded with ``b'\0'`` so its length is a
|
||||
multiple of 4 bytes before encoding.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
|
||||
.. function:: a2b_z85(string, /)
|
||||
|
||||
Convert Z85 data back to binary and return the binary data.
|
||||
More than one line may be passed at a time.
|
||||
|
||||
Valid Z85 data contains characters from the Z85 alphabet in groups
|
||||
of five (except for the final group, which may have from two to five
|
||||
characters). Each group encodes 32 bits of binary data in the range from
|
||||
``0`` to ``2 ** 32 - 1``, inclusive.
|
||||
|
||||
See `Z85 specification <https://rfc.zeromq.org/spec/32/>`_ for more information.
|
||||
|
||||
Invalid Z85 data will raise :exc:`binascii.Error`.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
|
||||
.. function:: b2a_z85(data, /, *, pad=False)
|
||||
|
||||
Convert binary data to a line of ASCII characters in Z85 coding.
|
||||
The return value is the converted line.
|
||||
Optional *alphabet* must be a :term:`bytes-like object` of length 85 which
|
||||
specifies an alternative alphabet.
|
||||
|
||||
If *pad* is true, the input is padded with ``b'\0'`` so its length is a
|
||||
multiple of 4 bytes before encoding.
|
||||
|
||||
See `Z85 specification <https://rfc.zeromq.org/spec/32/>`_ for more information.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
|
||||
@@ -300,6 +279,55 @@ The :mod:`!binascii` module defines the following functions:
|
||||
but may be handled by reading a little more data and trying again.
|
||||
|
||||
|
||||
.. data:: BASE64_ALPHABET
|
||||
|
||||
The Base 64 alphabet according to :rfc:`4648`.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. data:: URLSAFE_BASE64_ALPHABET
|
||||
|
||||
The "URL and filename safe" Base 64 alphabet according to :rfc:`4648`.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. data:: UU_ALPHABET
|
||||
|
||||
The uuencoding alphabet.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. data:: CRYPT_ALPHABET
|
||||
|
||||
The Base 64 alphabet used in the :manpage:`crypt(3)` routine and in the GEDCOM format.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. data:: BINHEX_ALPHABET
|
||||
|
||||
The Base 64 alphabet used in BinHex 4 (HQX) within the classic Mac OS.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. data:: BASE85_ALPHABET
|
||||
|
||||
The Base85 alphabet.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. data:: ASCII85_ALPHABET
|
||||
|
||||
The Ascii85 alphabet.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. data:: Z85_ALPHABET
|
||||
|
||||
The `Z85 <https://rfc.zeromq.org/spec/32/>`_ alphabet.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
Module :mod:`base64`
|
||||
|
||||
@@ -649,13 +649,16 @@ binascii
|
||||
|
||||
- :func:`~binascii.b2a_ascii85` and :func:`~binascii.a2b_ascii85`
|
||||
- :func:`~binascii.b2a_base85` and :func:`~binascii.a2b_base85`
|
||||
- :func:`~binascii.b2a_z85` and :func:`~binascii.a2b_z85`
|
||||
|
||||
(Contributed by James Seo and Serhiy Storchaka in :gh:`101178`.)
|
||||
|
||||
* Added the *wrapcol* parameter in :func:`~binascii.b2a_base64`.
|
||||
(Contributed by Serhiy Storchaka in :gh:`143214`.)
|
||||
|
||||
* Added the *alphabet* parameter in :func:`~binascii.b2a_base64` and
|
||||
:func:`~binascii.a2b_base64`.
|
||||
(Contributed by Serhiy Storchaka in :gh:`145980`.)
|
||||
|
||||
* Added the *ignorechars* parameter in :func:`~binascii.a2b_base64`.
|
||||
(Contributed by Serhiy Storchaka in :gh:`144001`.)
|
||||
|
||||
|
||||
@@ -1584,6 +1584,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(all));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(all_threads));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(allow_code));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(alphabet));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(any));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(append));
|
||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(arg));
|
||||
|
||||
@@ -307,6 +307,7 @@ struct _Py_global_strings {
|
||||
STRUCT_FOR_ID(all)
|
||||
STRUCT_FOR_ID(all_threads)
|
||||
STRUCT_FOR_ID(allow_code)
|
||||
STRUCT_FOR_ID(alphabet)
|
||||
STRUCT_FOR_ID(any)
|
||||
STRUCT_FOR_ID(append)
|
||||
STRUCT_FOR_ID(arg)
|
||||
|
||||
@@ -1582,6 +1582,7 @@ extern "C" {
|
||||
INIT_ID(all), \
|
||||
INIT_ID(all_threads), \
|
||||
INIT_ID(allow_code), \
|
||||
INIT_ID(alphabet), \
|
||||
INIT_ID(any), \
|
||||
INIT_ID(append), \
|
||||
INIT_ID(arg), \
|
||||
|
||||
@@ -1008,6 +1008,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
|
||||
_PyUnicode_InternStatic(interp, &string);
|
||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||
assert(PyUnicode_GET_LENGTH(string) != 1);
|
||||
string = &_Py_ID(alphabet);
|
||||
_PyUnicode_InternStatic(interp, &string);
|
||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||
assert(PyUnicode_GET_LENGTH(string) != 1);
|
||||
string = &_Py_ID(any);
|
||||
_PyUnicode_InternStatic(interp, &string);
|
||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||
|
||||
+14
-17
@@ -56,11 +56,13 @@ def b64encode(s, altchars=None, *, wrapcol=0):
|
||||
If wrapcol is non-zero, insert a newline (b'\\n') character after at most
|
||||
every wrapcol characters.
|
||||
"""
|
||||
encoded = binascii.b2a_base64(s, wrapcol=wrapcol, newline=False)
|
||||
if altchars is not None:
|
||||
assert len(altchars) == 2, repr(altchars)
|
||||
return encoded.translate(bytes.maketrans(b'+/', altchars))
|
||||
return encoded
|
||||
if len(altchars) != 2:
|
||||
raise ValueError(f'invalid altchars: {altchars!r}')
|
||||
alphabet = binascii.BASE64_ALPHABET[:-2] + altchars
|
||||
return binascii.b2a_base64(s, wrapcol=wrapcol, newline=False,
|
||||
alphabet=alphabet)
|
||||
return binascii.b2a_base64(s, wrapcol=wrapcol, newline=False)
|
||||
|
||||
|
||||
def b64decode(s, altchars=None, validate=_NOT_SPECIFIED, *, ignorechars=_NOT_SPECIFIED):
|
||||
@@ -100,15 +102,10 @@ def b64decode(s, altchars=None, validate=_NOT_SPECIFIED, *, ignorechars=_NOT_SPE
|
||||
break
|
||||
s = s.translate(bytes.maketrans(altchars, b'+/'))
|
||||
else:
|
||||
trans_in = set(b'+/') - set(altchars)
|
||||
if len(trans_in) == 2:
|
||||
# we can't use the reqult of unordered sets here
|
||||
trans = bytes.maketrans(altchars + b'+/', b'+/' + altchars)
|
||||
else:
|
||||
trans = bytes.maketrans(altchars + bytes(trans_in),
|
||||
b'+/' + bytes(set(altchars) - set(b'+/')))
|
||||
s = s.translate(trans)
|
||||
ignorechars = ignorechars.translate(trans)
|
||||
alphabet = binascii.BASE64_ALPHABET[:-2] + altchars
|
||||
return binascii.a2b_base64(s, strict_mode=validate,
|
||||
alphabet=alphabet,
|
||||
ignorechars=ignorechars)
|
||||
if ignorechars is _NOT_SPECIFIED:
|
||||
ignorechars = b''
|
||||
result = binascii.a2b_base64(s, strict_mode=validate,
|
||||
@@ -146,7 +143,6 @@ def standard_b64decode(s):
|
||||
return b64decode(s)
|
||||
|
||||
|
||||
_urlsafe_encode_translation = bytes.maketrans(b'+/', b'-_')
|
||||
_urlsafe_decode_translation = bytes.maketrans(b'-_', b'+/')
|
||||
|
||||
def urlsafe_b64encode(s):
|
||||
@@ -156,7 +152,8 @@ def urlsafe_b64encode(s):
|
||||
bytes object. The alphabet uses '-' instead of '+' and '_' instead of
|
||||
'/'.
|
||||
"""
|
||||
return b64encode(s).translate(_urlsafe_encode_translation)
|
||||
return binascii.b2a_base64(s, newline=False,
|
||||
alphabet=binascii.URLSAFE_BASE64_ALPHABET)
|
||||
|
||||
def urlsafe_b64decode(s):
|
||||
"""Decode bytes using the URL- and filesystem-safe Base64 alphabet.
|
||||
@@ -399,14 +396,14 @@ def b85decode(b):
|
||||
|
||||
def z85encode(s, pad=False):
|
||||
"""Encode bytes-like object b in z85 format and return a bytes object."""
|
||||
return binascii.b2a_z85(s, pad=pad)
|
||||
return binascii.b2a_base85(s, pad=pad, alphabet=binascii.Z85_ALPHABET)
|
||||
|
||||
def z85decode(s):
|
||||
"""Decode the z85-encoded bytes-like object or ASCII string b
|
||||
|
||||
The result is returned as a bytes object.
|
||||
"""
|
||||
return binascii.a2b_z85(s)
|
||||
return binascii.a2b_base85(s, alphabet=binascii.Z85_ALPHABET)
|
||||
|
||||
# Legacy interface. This code could be cleaned up since I don't believe
|
||||
# binascii has any line length limitations. It just doesn't seem worth it
|
||||
|
||||
+82
-67
@@ -10,10 +10,10 @@ from test.support.hypothesis_helper import hypothesis
|
||||
|
||||
|
||||
# Note: "*_hex" functions are aliases for "(un)hexlify"
|
||||
b2a_functions = ['b2a_ascii85', 'b2a_base64', 'b2a_base85', 'b2a_z85',
|
||||
b2a_functions = ['b2a_ascii85', 'b2a_base64', 'b2a_base85',
|
||||
'b2a_hex', 'b2a_qp', 'b2a_uu',
|
||||
'hexlify']
|
||||
a2b_functions = ['a2b_ascii85', 'a2b_base64', 'a2b_base85', 'a2b_z85',
|
||||
a2b_functions = ['a2b_ascii85', 'a2b_base64', 'a2b_base85',
|
||||
'a2b_hex', 'a2b_qp', 'a2b_uu',
|
||||
'unhexlify']
|
||||
all_functions = a2b_functions + b2a_functions + ['crc32', 'crc_hqx']
|
||||
@@ -46,6 +46,35 @@ class BinASCIITest(unittest.TestCase):
|
||||
self.assertIsSubclass(binascii.Error, Exception)
|
||||
self.assertIsSubclass(binascii.Incomplete, Exception)
|
||||
|
||||
def test_constants(self):
|
||||
self.assertEqual(binascii.BASE64_ALPHABET,
|
||||
b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
b'abcdefghijklmnopqrstuvwxyz'
|
||||
b'0123456789+/')
|
||||
self.assertEqual(binascii.URLSAFE_BASE64_ALPHABET,
|
||||
binascii.BASE64_ALPHABET[:-2] + b'-_')
|
||||
self.assertEqual(binascii.UU_ALPHABET, bytes(range(32, 32+64)))
|
||||
self.assertEqual(binascii.CRYPT_ALPHABET,
|
||||
b'./0123456789'
|
||||
b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
b'abcdefghijklmnopqrstuvwxyz')
|
||||
self.assertEqual(binascii.BINHEX_ALPHABET,
|
||||
b'!"#$%&\'()*+,-012345689'
|
||||
b'@ABCDEFGHIJKLMNPQRSTUVXYZ['
|
||||
b'`abcdefhijklmpqr')
|
||||
|
||||
self.assertEqual(binascii.BASE85_ALPHABET,
|
||||
b'0123456789'
|
||||
b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
b'abcdefghijklmnopqrstuvwxyz'
|
||||
b'!#$%&()*+-;<=>?@^_`{|}~')
|
||||
self.assertEqual(binascii.ASCII85_ALPHABET, bytes(range(33, 33+85)))
|
||||
self.assertEqual(binascii.Z85_ALPHABET,
|
||||
b'0123456789'
|
||||
b'abcdefghijklmnopqrstuvwxyz'
|
||||
b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
b'.-:+=^!/*?&<>()[]{}@%$#')
|
||||
|
||||
def test_functions(self):
|
||||
# Check presence of all functions
|
||||
for name in all_functions:
|
||||
@@ -302,6 +331,33 @@ class BinASCIITest(unittest.TestCase):
|
||||
assertInvalidLength(b'A\tB\nC ??DE', # only 5 valid characters
|
||||
strict_mode=False)
|
||||
|
||||
def test_base64_alphabet(self):
|
||||
alphabet = (b'!"#$%&\'()*+,-012345689@'
|
||||
b'ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr')
|
||||
data = self.type2test(self.rawdata)
|
||||
encoded = binascii.b2a_base64(data, alphabet=alphabet)
|
||||
trans = bytes.maketrans(binascii.BASE64_ALPHABET, alphabet)
|
||||
expected = binascii.b2a_base64(data).translate(trans)
|
||||
self.assertEqual(encoded, expected)
|
||||
self.assertEqual(binascii.a2b_base64(encoded, alphabet=alphabet), self.rawdata)
|
||||
self.assertEqual(binascii.b2a_base64(data, alphabet=self.type2test(alphabet)), expected)
|
||||
|
||||
data = self.type2test(b'')
|
||||
self.assertEqual(binascii.b2a_base64(data, alphabet=alphabet), b'\n')
|
||||
self.assertEqual(binascii.a2b_base64(data, alphabet=alphabet), b'')
|
||||
|
||||
for func in binascii.b2a_base64, binascii.a2b_base64:
|
||||
with self.assertRaises(TypeError):
|
||||
func(data, alphabet=None)
|
||||
with self.assertRaises(TypeError):
|
||||
func(data, alphabet=alphabet.decode())
|
||||
with self.assertRaises(ValueError):
|
||||
func(data, alphabet=alphabet[:-1])
|
||||
with self.assertRaises(ValueError):
|
||||
func(data, alphabet=alphabet+b'?')
|
||||
with self.assertRaises(TypeError):
|
||||
binascii.a2b_base64(data, alphabet=bytearray(alphabet))
|
||||
|
||||
def test_ascii85_valid(self):
|
||||
# Test Ascii85 with valid data
|
||||
ASCII85_PREFIX = b"<~"
|
||||
@@ -587,73 +643,32 @@ class BinASCIITest(unittest.TestCase):
|
||||
b_pad_expected = b + b"\0" * padding
|
||||
self.assertEqual(b_pad, b_pad_expected)
|
||||
|
||||
def test_z85_valid(self):
|
||||
# Test Z85 with valid data
|
||||
lines, i = [], 0
|
||||
for k in range(1, len(self.rawdata) + 1):
|
||||
b = self.type2test(self.rawdata[i:i + k])
|
||||
a = binascii.b2a_z85(b)
|
||||
lines.append(a)
|
||||
i += k
|
||||
if i >= len(self.rawdata):
|
||||
break
|
||||
res = bytes()
|
||||
for line in lines:
|
||||
a = self.type2test(line)
|
||||
b = binascii.a2b_z85(a)
|
||||
res += b
|
||||
self.assertEqual(res, self.rawdata)
|
||||
def test_base85_alphabet(self):
|
||||
alphabet = (b'0123456789abcdefghijklmnopqrstuvwxyz'
|
||||
b'ABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#')
|
||||
data = self.type2test(self.rawdata)
|
||||
encoded = binascii.b2a_base85(data, alphabet=alphabet)
|
||||
trans = bytes.maketrans(binascii.BASE85_ALPHABET, alphabet)
|
||||
expected = binascii.b2a_base85(data).translate(trans)
|
||||
self.assertEqual(encoded, expected)
|
||||
self.assertEqual(binascii.a2b_base85(encoded, alphabet=alphabet), self.rawdata)
|
||||
self.assertEqual(binascii.b2a_base85(data, alphabet=self.type2test(alphabet)), expected)
|
||||
|
||||
# Test decoding inputs with different length
|
||||
self.assertEqual(binascii.a2b_z85(self.type2test(b'')), b'')
|
||||
self.assertEqual(binascii.a2b_z85(self.type2test(b'a')), b'')
|
||||
self.assertEqual(binascii.a2b_z85(self.type2test(b'ab')), b'\x1f')
|
||||
self.assertEqual(binascii.a2b_z85(self.type2test(b'abc')),
|
||||
b'\x1f\x85')
|
||||
self.assertEqual(binascii.a2b_z85(self.type2test(b'abcd')),
|
||||
b'\x1f\x85\x9a')
|
||||
self.assertEqual(binascii.a2b_z85(self.type2test(b'abcde')),
|
||||
b'\x1f\x85\x9a$')
|
||||
self.assertEqual(binascii.a2b_z85(self.type2test(b'abcdef')),
|
||||
b'\x1f\x85\x9a$')
|
||||
self.assertEqual(binascii.a2b_z85(self.type2test(b'abcdefg')),
|
||||
b'\x1f\x85\x9a$/')
|
||||
data = self.type2test(b'')
|
||||
self.assertEqual(binascii.b2a_base85(data, alphabet=alphabet), b'')
|
||||
self.assertEqual(binascii.a2b_base85(data, alphabet=alphabet), b'')
|
||||
|
||||
def test_z85_errors(self):
|
||||
def _assertRegexTemplate(assert_regex, data, **kwargs):
|
||||
with self.assertRaisesRegex(binascii.Error, assert_regex):
|
||||
binascii.a2b_z85(self.type2test(data), **kwargs)
|
||||
|
||||
def assertNonZ85Data(data):
|
||||
_assertRegexTemplate(r"(?i)bad z85 character", data)
|
||||
|
||||
def assertOverflow(data):
|
||||
_assertRegexTemplate(r"(?i)z85 overflow", data)
|
||||
|
||||
assertNonZ85Data(b"\xda")
|
||||
assertNonZ85Data(b"00\0\0")
|
||||
assertNonZ85Data(b"z !/")
|
||||
assertNonZ85Data(b"By/JnB0hYQ\n")
|
||||
|
||||
# Test Z85 with out-of-range encoded value
|
||||
assertOverflow(b"%")
|
||||
assertOverflow(b"%n")
|
||||
assertOverflow(b"%nS")
|
||||
assertOverflow(b"%nSc")
|
||||
assertOverflow(b"%nSc1")
|
||||
assertOverflow(b"%nSc0$")
|
||||
assertOverflow(b"%nSc0%nSc0%nSD0")
|
||||
|
||||
def test_z85_pad(self):
|
||||
# Test Z85 with encode padding
|
||||
rawdata = b"n1n3Tee\n ch@rAc\te\r$"
|
||||
for i in range(1, len(rawdata) + 1):
|
||||
padding = -i % 4
|
||||
b = rawdata[:i]
|
||||
a_pad = binascii.b2a_z85(self.type2test(b), pad=True)
|
||||
b_pad = binascii.a2b_z85(self.type2test(a_pad))
|
||||
b_pad_expected = b + b"\0" * padding
|
||||
self.assertEqual(b_pad, b_pad_expected)
|
||||
for func in binascii.b2a_base85, binascii.a2b_base85:
|
||||
with self.assertRaises(TypeError):
|
||||
func(data, alphabet=None)
|
||||
with self.assertRaises(TypeError):
|
||||
func(data, alphabet=alphabet.decode())
|
||||
with self.assertRaises(ValueError):
|
||||
func(data, alphabet=alphabet[:-1])
|
||||
with self.assertRaises(ValueError):
|
||||
func(data, alphabet=alphabet+b'?')
|
||||
with self.assertRaises(TypeError):
|
||||
binascii.a2b_base64(data, alphabet=bytearray(alphabet))
|
||||
|
||||
def test_uu(self):
|
||||
MAX_UU = 45
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
Added the *alphabet* parameter in :func:`~binascii.b2a_base64`,
|
||||
:func:`~binascii.a2b_base64`, :func:`~binascii.b2a_base85` and
|
||||
:func:`~binascii.a2b_base85` and a number of ``*_ALPHABET`` constants in the
|
||||
:mod:`binascii` module. Removed :func:`!b2a_z85` and
|
||||
:func:`!a2b_z85`.
|
||||
+207
-116
@@ -67,6 +67,7 @@
|
||||
typedef struct binascii_state {
|
||||
PyObject *Error;
|
||||
PyObject *Incomplete;
|
||||
PyObject *reverse_table_cache;
|
||||
} binascii_state;
|
||||
|
||||
static inline binascii_state *
|
||||
@@ -228,26 +229,6 @@ static const unsigned char table_a2b_base85_a85[] Py_ALIGNED(64) = {
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
};
|
||||
|
||||
static const unsigned char table_a2b_base85_z85[] Py_ALIGNED(64) = {
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,68,-1,84, 83,82,72,-1, 75,76,70,65, -1,63,62,69,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,64,-1, 73,66,74,71,
|
||||
81,36,37,38, 39,40,41,42, 43,44,45,46, 47,48,49,50,
|
||||
51,52,53,54, 55,56,57,58, 59,60,61,77, -1,78,67,-1,
|
||||
-1,10,11,12, 13,14,15,16, 17,18,19,20, 21,22,23,24,
|
||||
25,26,27,28, 29,30,31,32, 33,34,35,79, -1,80,-1,-1,
|
||||
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
};
|
||||
|
||||
static const unsigned char table_b2a_base85[] Py_ALIGNED(64) =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
|
||||
"abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
|
||||
@@ -256,9 +237,6 @@ static const unsigned char table_b2a_base85_a85[] Py_ALIGNED(64) =
|
||||
"!\"#$%&\'()*+,-./0123456789:;<=>?@" \
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu";
|
||||
|
||||
static const unsigned char table_b2a_base85_z85[] Py_ALIGNED(64) =
|
||||
"0123456789abcdefghijklmnopqrstuvwxyz" \
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/\x2a?&<>()[]{}@%$#"; /* clinic doesn't like '/' followed by '*' */
|
||||
|
||||
#define BASE85_A85_PREFIX '<'
|
||||
#define BASE85_A85_AFFIX '~'
|
||||
@@ -547,6 +525,52 @@ binascii_b2a_uu_impl(PyObject *module, Py_buffer *data, int backtick)
|
||||
return PyBytesWriter_FinishWithPointer(writer, ascii_data);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
get_reverse_table(binascii_state *state, PyObject *alphabet, int size, int padchar)
|
||||
{
|
||||
PyObject *reverse_table;
|
||||
if (state == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyBytes_GET_SIZE(alphabet) != size) {
|
||||
PyErr_Format(PyExc_ValueError, "alphabet must have length %d", size);
|
||||
return NULL;
|
||||
}
|
||||
if (PyDict_GetItemRef(state->reverse_table_cache, alphabet, &reverse_table) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (reverse_table == NULL) {
|
||||
unsigned char out[256];
|
||||
memset(out, (unsigned char)-1, 256);
|
||||
const unsigned char *in = (const unsigned char *)PyBytes_AS_STRING(alphabet);
|
||||
for (int i = 0; i < size; i++) {
|
||||
out[in[i]] = i;
|
||||
}
|
||||
if (padchar >= 0) {
|
||||
assert(padchar < 256);
|
||||
out[padchar] = size;
|
||||
}
|
||||
reverse_table = PyBytes_FromStringAndSize((char *)out, 256);
|
||||
if (reverse_table == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyDict_SetItem(state->reverse_table_cache, alphabet, reverse_table) < 0) {
|
||||
Py_DECREF(reverse_table);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!PyBytes_Check(reverse_table)
|
||||
|| PyBytes_GET_SIZE(reverse_table) != 256)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "Broken binascii cache");
|
||||
Py_DECREF(reverse_table);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return reverse_table;
|
||||
}
|
||||
|
||||
typedef unsigned char ignorecache_t[32];
|
||||
|
||||
static int
|
||||
@@ -576,6 +600,7 @@ binascii.a2b_base64
|
||||
When set to true, bytes that are not part of the base64 standard are
|
||||
not allowed. The same applies to excess data after padding (= / ==).
|
||||
Set to True by default if ignorechars is specified, False otherwise.
|
||||
alphabet: PyBytesObject(c_default="NULL") = BASE64_ALPHABET
|
||||
ignorechars: Py_buffer = NULL
|
||||
A byte string containing characters to ignore from the input when
|
||||
strict_mode is true.
|
||||
@@ -585,14 +610,16 @@ Decode a line of base64 data.
|
||||
|
||||
static PyObject *
|
||||
binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode,
|
||||
Py_buffer *ignorechars)
|
||||
/*[clinic end generated code: output=eab37aea4cfa6daa input=d2d238abf13822ed]*/
|
||||
PyBytesObject *alphabet, Py_buffer *ignorechars)
|
||||
/*[clinic end generated code: output=72f15fcc0681d666 input=195c8d60b03aaa6f]*/
|
||||
{
|
||||
assert(data->len >= 0);
|
||||
|
||||
const unsigned char *ascii_data = data->buf;
|
||||
size_t ascii_len = data->len;
|
||||
binascii_state *state = NULL;
|
||||
PyObject *table_obj = NULL;
|
||||
const unsigned char *table_a2b = table_a2b_base64;
|
||||
|
||||
if (strict_mode == -1) {
|
||||
strict_mode = (ignorechars->buf != NULL);
|
||||
@@ -605,10 +632,20 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode,
|
||||
memset(ignorecache, 0, sizeof(ignorecache));
|
||||
}
|
||||
|
||||
if (alphabet != NULL) {
|
||||
state = get_binascii_state(module);
|
||||
table_obj = get_reverse_table(state, (PyObject *)alphabet, 64, BASE64_PAD);
|
||||
if (table_obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
table_a2b = (const unsigned char *)PyBytes_AS_STRING(table_obj);
|
||||
}
|
||||
|
||||
/* Allocate the buffer */
|
||||
Py_ssize_t bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */
|
||||
PyBytesWriter *writer = PyBytesWriter_Create(bin_len);
|
||||
if (writer == NULL) {
|
||||
Py_XDECREF(table_obj);
|
||||
return NULL;
|
||||
}
|
||||
unsigned char *bin_data = PyBytesWriter_GetData(writer);
|
||||
@@ -620,7 +657,7 @@ fastpath:
|
||||
*/
|
||||
if (ascii_len >= 4) {
|
||||
Py_ssize_t fast_chars = base64_decode_fast(ascii_data, (Py_ssize_t)ascii_len,
|
||||
bin_data, table_a2b_base64);
|
||||
bin_data, table_a2b);
|
||||
if (fast_chars > 0) {
|
||||
ascii_data += fast_chars;
|
||||
ascii_len -= fast_chars;
|
||||
@@ -672,7 +709,7 @@ fastpath:
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char v = table_a2b_base64[this_ch];
|
||||
unsigned char v = table_a2b[this_ch];
|
||||
if (v >= 64) {
|
||||
if (strict_mode && !ignorechar(this_ch, ignorechars, ignorecache)) {
|
||||
state = get_binascii_state(module);
|
||||
@@ -749,9 +786,11 @@ fastpath:
|
||||
}
|
||||
|
||||
done:
|
||||
Py_XDECREF(table_obj);
|
||||
return PyBytesWriter_FinishWithPointer(writer, bin_data);
|
||||
|
||||
error_end:
|
||||
Py_XDECREF(table_obj);
|
||||
PyBytesWriter_Discard(writer);
|
||||
return NULL;
|
||||
}
|
||||
@@ -765,19 +804,28 @@ binascii.b2a_base64
|
||||
*
|
||||
wrapcol: size_t = 0
|
||||
newline: bool = True
|
||||
alphabet: Py_buffer(c_default="{NULL, NULL}") = BASE64_ALPHABET
|
||||
|
||||
Base64-code line of data.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol,
|
||||
int newline)
|
||||
/*[clinic end generated code: output=2edc7311a9515eac input=2ee4214e6d489e2e]*/
|
||||
int newline, Py_buffer *alphabet)
|
||||
/*[clinic end generated code: output=9d9657e5fbe28c64 input=ffa3af8520c312ac]*/
|
||||
{
|
||||
const unsigned char *table_b2a = table_b2a_base64;
|
||||
const unsigned char *bin_data = data->buf;
|
||||
Py_ssize_t bin_len = data->len;
|
||||
assert(bin_len >= 0);
|
||||
|
||||
if (alphabet->buf != NULL) {
|
||||
if (alphabet->len != 64) {
|
||||
PyErr_SetString(PyExc_ValueError, "alphabet must have length 64");
|
||||
return NULL;
|
||||
}
|
||||
table_b2a = alphabet->buf;
|
||||
}
|
||||
/* Each group of 3 bytes (rounded up) gets encoded as 4 characters,
|
||||
* not counting newlines.
|
||||
* Note that 'b' gets encoded as 'Yg==' (1 in, 4 out).
|
||||
@@ -809,7 +857,7 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol,
|
||||
|
||||
/* Use the optimized fast path for complete 3-byte groups */
|
||||
Py_ssize_t fast_bytes = base64_encode_fast(bin_data, bin_len, ascii_data,
|
||||
table_b2a_base64);
|
||||
table_b2a);
|
||||
bin_data += fast_bytes;
|
||||
ascii_data += (fast_bytes / 3) * 4;
|
||||
bin_len -= fast_bytes;
|
||||
@@ -818,17 +866,17 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol,
|
||||
if (bin_len == 1) {
|
||||
/* 1 byte remaining: produces 2 base64 chars + 2 padding */
|
||||
unsigned int val = bin_data[0];
|
||||
*ascii_data++ = table_b2a_base64[(val >> 2) & 0x3f];
|
||||
*ascii_data++ = table_b2a_base64[(val << 4) & 0x3f];
|
||||
*ascii_data++ = table_b2a[(val >> 2) & 0x3f];
|
||||
*ascii_data++ = table_b2a[(val << 4) & 0x3f];
|
||||
*ascii_data++ = BASE64_PAD;
|
||||
*ascii_data++ = BASE64_PAD;
|
||||
}
|
||||
else if (bin_len == 2) {
|
||||
/* 2 bytes remaining: produces 3 base64 chars + 1 padding */
|
||||
unsigned int val = ((unsigned int)bin_data[0] << 8) | bin_data[1];
|
||||
*ascii_data++ = table_b2a_base64[(val >> 10) & 0x3f];
|
||||
*ascii_data++ = table_b2a_base64[(val >> 4) & 0x3f];
|
||||
*ascii_data++ = table_b2a_base64[(val << 2) & 0x3f];
|
||||
*ascii_data++ = table_b2a[(val >> 10) & 0x3f];
|
||||
*ascii_data++ = table_b2a[(val >> 4) & 0x3f];
|
||||
*ascii_data++ = table_b2a[(val << 2) & 0x3f];
|
||||
*ascii_data++ = BASE64_PAD;
|
||||
}
|
||||
|
||||
@@ -1123,13 +1171,36 @@ binascii_b2a_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces,
|
||||
return PyBytesWriter_FinishWithPointer(writer, ascii_data);
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
binascii.a2b_base85
|
||||
|
||||
data: ascii_buffer
|
||||
/
|
||||
*
|
||||
alphabet: PyBytesObject(c_default="NULL") = BASE85_ALPHABET
|
||||
|
||||
Decode a line of Base85 data.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
base85_decode_impl(PyObject *module, Py_buffer *data,
|
||||
const unsigned char table_a2b[], const char *name)
|
||||
binascii_a2b_base85_impl(PyObject *module, Py_buffer *data,
|
||||
PyBytesObject *alphabet)
|
||||
/*[clinic end generated code: output=3e114af53812e8ff input=0b6b83b38ad4497c]*/
|
||||
{
|
||||
const unsigned char *ascii_data = data->buf;
|
||||
Py_ssize_t ascii_len = data->len;
|
||||
binascii_state *state = NULL;
|
||||
PyObject *table_obj = NULL;
|
||||
const unsigned char *table_a2b = table_a2b_base85;
|
||||
|
||||
if (alphabet != NULL) {
|
||||
state = get_binascii_state(module);
|
||||
table_obj = get_reverse_table(state, (PyObject *)alphabet, 85, -1);
|
||||
if (table_obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
table_a2b = (const unsigned char *)PyBytes_AS_STRING(table_obj);
|
||||
}
|
||||
|
||||
assert(ascii_len >= 0);
|
||||
|
||||
@@ -1137,6 +1208,7 @@ base85_decode_impl(PyObject *module, Py_buffer *data,
|
||||
size_t bin_len = ((size_t)ascii_len + 4) / 5 * 4;
|
||||
PyBytesWriter *writer = PyBytesWriter_Create(bin_len);
|
||||
if (writer == NULL) {
|
||||
Py_XDECREF(table_obj);
|
||||
return NULL;
|
||||
}
|
||||
unsigned char *bin_data = PyBytesWriter_GetData(writer);
|
||||
@@ -1162,8 +1234,8 @@ base85_decode_impl(PyObject *module, Py_buffer *data,
|
||||
state = get_binascii_state(module);
|
||||
if (state != NULL) {
|
||||
PyErr_Format(state->Error,
|
||||
"%s overflow in hunk starting at byte %d",
|
||||
name, (data->len - ascii_len) / 5 * 5);
|
||||
"Base85 overflow in hunk starting at byte %d",
|
||||
(data->len - ascii_len) / 5 * 5);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
@@ -1173,8 +1245,8 @@ base85_decode_impl(PyObject *module, Py_buffer *data,
|
||||
else {
|
||||
state = get_binascii_state(module);
|
||||
if (state != NULL) {
|
||||
PyErr_Format(state->Error, "bad %s character at position %d",
|
||||
name, data->len - ascii_len);
|
||||
PyErr_Format(state->Error, "bad Base85 character at position %d",
|
||||
data->len - ascii_len);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
@@ -1194,19 +1266,44 @@ base85_decode_impl(PyObject *module, Py_buffer *data,
|
||||
leftchar = 0;
|
||||
}
|
||||
|
||||
Py_XDECREF(table_obj);
|
||||
return PyBytesWriter_FinishWithPointer(writer, bin_data);
|
||||
|
||||
error:
|
||||
PyBytesWriter_Discard(writer);
|
||||
Py_XDECREF(table_obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
binascii.b2a_base85
|
||||
|
||||
data: Py_buffer
|
||||
/
|
||||
*
|
||||
pad: bool = False
|
||||
Pad input to a multiple of 4 before encoding.
|
||||
alphabet: Py_buffer(c_default="{NULL, NULL}") = BASE85_ALPHABET
|
||||
|
||||
Base85-code line of data.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
base85_encode_impl(PyObject *module, Py_buffer *data, int pad,
|
||||
const unsigned char table_b2a[], const char *name)
|
||||
binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad,
|
||||
Py_buffer *alphabet)
|
||||
/*[clinic end generated code: output=a59f4f2ff6f0e69f input=30f545c6ff554db7]*/
|
||||
{
|
||||
const unsigned char *bin_data = data->buf;
|
||||
Py_ssize_t bin_len = data->len;
|
||||
const unsigned char *table_b2a = table_b2a_base85;
|
||||
|
||||
if (alphabet->buf != NULL) {
|
||||
if (alphabet->len != 85) {
|
||||
PyErr_SetString(PyExc_ValueError, "alphabet must have length 85");
|
||||
return NULL;
|
||||
}
|
||||
table_b2a = alphabet->buf;
|
||||
}
|
||||
|
||||
assert(bin_len >= 0);
|
||||
|
||||
@@ -1220,7 +1317,7 @@ base85_encode_impl(PyObject *module, Py_buffer *data, int pad,
|
||||
if (state == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyErr_Format(state->Error, "Too much data for %s", name);
|
||||
PyErr_SetString(state->Error, "Too much data for Base85");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1270,76 +1367,6 @@ base85_encode_impl(PyObject *module, Py_buffer *data, int pad,
|
||||
return PyBytesWriter_FinishWithPointer(writer, ascii_data);
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
binascii.a2b_base85
|
||||
|
||||
data: ascii_buffer
|
||||
/
|
||||
|
||||
Decode a line of Base85 data.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
binascii_a2b_base85_impl(PyObject *module, Py_buffer *data)
|
||||
/*[clinic end generated code: output=c2db6ab9181b0089 input=06c9d595352b5a2b]*/
|
||||
{
|
||||
return base85_decode_impl(module, data, table_a2b_base85, "Base85");
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
binascii.b2a_base85
|
||||
|
||||
data: Py_buffer
|
||||
/
|
||||
*
|
||||
pad: bool = False
|
||||
Pad input to a multiple of 4 before encoding.
|
||||
|
||||
Base85-code line of data.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad)
|
||||
/*[clinic end generated code: output=b317adb36a57740d input=89fde81b96dcec06]*/
|
||||
{
|
||||
return base85_encode_impl(module, data, pad, table_b2a_base85, "Base85");
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
binascii.a2b_z85
|
||||
|
||||
data: ascii_buffer
|
||||
/
|
||||
|
||||
Decode a line of Z85 data.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
binascii_a2b_z85_impl(PyObject *module, Py_buffer *data)
|
||||
/*[clinic end generated code: output=57d8260bb5267a98 input=c54baff4d81510a4]*/
|
||||
{
|
||||
return base85_decode_impl(module, data, table_a2b_base85_z85, "Z85");
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
binascii.b2a_z85
|
||||
|
||||
data: Py_buffer
|
||||
/
|
||||
*
|
||||
pad: bool = False
|
||||
Pad input to a multiple of 4 before encoding.
|
||||
|
||||
Z85-code line of data.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
binascii_b2a_z85_impl(PyObject *module, Py_buffer *data, int pad)
|
||||
/*[clinic end generated code: output=88284835e332c9cf input=51d070a5a6cf82d8]*/
|
||||
{
|
||||
return base85_encode_impl(module, data, pad, table_b2a_base85_z85, "Z85");
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
binascii.crc_hqx
|
||||
|
||||
@@ -2001,8 +2028,6 @@ static struct PyMethodDef binascii_module_methods[] = {
|
||||
BINASCII_A2B_ASCII85_METHODDEF
|
||||
BINASCII_A2B_BASE85_METHODDEF
|
||||
BINASCII_B2A_BASE85_METHODDEF
|
||||
BINASCII_A2B_Z85_METHODDEF
|
||||
BINASCII_B2A_Z85_METHODDEF
|
||||
BINASCII_A2B_HEX_METHODDEF
|
||||
BINASCII_B2A_HEX_METHODDEF
|
||||
BINASCII_HEXLIFY_METHODDEF
|
||||
@@ -2036,6 +2061,70 @@ binascii_exec(PyObject *module)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PyModule_Add(module, "BASE64_ALPHABET",
|
||||
PyBytes_FromStringAndSize((const char *)table_b2a_base64, 64)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_Add(module, "URLSAFE_BASE64_ALPHABET",
|
||||
PyBytes_FromString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789-_")) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_Add(module, "CRYPT_ALPHABET",
|
||||
PyBytes_FromString("./0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz")) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_Add(module, "UU_ALPHABET",
|
||||
PyBytes_FromString(" !\"#$%&'()*+,-./"
|
||||
"0123456789:;<=>?@"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"[\\]^_")) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_Add(module, "BINHEX_ALPHABET",
|
||||
PyBytes_FromString("!\"#$%&'()*+,-012345689@"
|
||||
"ABCDEFGHIJKLMNPQRSTUVXYZ[`"
|
||||
"abcdefhijklmpqr")) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_Add(module, "BASE85_ALPHABET",
|
||||
PyBytes_FromStringAndSize((const char *)table_b2a_base85, 85)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_Add(module, "ASCII85_ALPHABET",
|
||||
PyBytes_FromStringAndSize((const char *)table_b2a_base85_a85, 85)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_Add(module, "Z85_ALPHABET",
|
||||
PyBytes_FromString("0123456789"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
/* clinic doesn't like '/' followed by '*' */
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
".-:+=^!/\x2a?&<>()[]{}@%$#")) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
state->reverse_table_cache = PyDict_New();
|
||||
if (state->reverse_table_cache == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
state->reverse_table_cache = PyDict_New();
|
||||
if (state->reverse_table_cache == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2052,6 +2141,7 @@ binascii_traverse(PyObject *module, visitproc visit, void *arg)
|
||||
binascii_state *state = get_binascii_state(module);
|
||||
Py_VISIT(state->Error);
|
||||
Py_VISIT(state->Incomplete);
|
||||
Py_VISIT(state->reverse_table_cache);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2061,6 +2151,7 @@ binascii_clear(PyObject *module)
|
||||
binascii_state *state = get_binascii_state(module);
|
||||
Py_CLEAR(state->Error);
|
||||
Py_CLEAR(state->Incomplete);
|
||||
Py_CLEAR(state->reverse_table_cache);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Generated
+117
-142
@@ -117,7 +117,7 @@ exit:
|
||||
|
||||
PyDoc_STRVAR(binascii_a2b_base64__doc__,
|
||||
"a2b_base64($module, data, /, *, strict_mode=<unrepresentable>,\n"
|
||||
" ignorechars=<unrepresentable>)\n"
|
||||
" alphabet=BASE64_ALPHABET, ignorechars=<unrepresentable>)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Decode a line of base64 data.\n"
|
||||
@@ -135,7 +135,7 @@ PyDoc_STRVAR(binascii_a2b_base64__doc__,
|
||||
|
||||
static PyObject *
|
||||
binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode,
|
||||
Py_buffer *ignorechars);
|
||||
PyBytesObject *alphabet, Py_buffer *ignorechars);
|
||||
|
||||
static PyObject *
|
||||
binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||
@@ -143,7 +143,7 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
PyObject *return_value = NULL;
|
||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
|
||||
#define NUM_KEYWORDS 2
|
||||
#define NUM_KEYWORDS 3
|
||||
static struct {
|
||||
PyGC_Head _this_is_not_used;
|
||||
PyObject_VAR_HEAD
|
||||
@@ -152,7 +152,7 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
} _kwtuple = {
|
||||
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
|
||||
.ob_hash = -1,
|
||||
.ob_item = { &_Py_ID(strict_mode), &_Py_ID(ignorechars), },
|
||||
.ob_item = { &_Py_ID(strict_mode), &_Py_ID(alphabet), &_Py_ID(ignorechars), },
|
||||
};
|
||||
#undef NUM_KEYWORDS
|
||||
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
|
||||
@@ -161,17 +161,18 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
# define KWTUPLE NULL
|
||||
#endif // !Py_BUILD_CORE
|
||||
|
||||
static const char * const _keywords[] = {"", "strict_mode", "ignorechars", NULL};
|
||||
static const char * const _keywords[] = {"", "strict_mode", "alphabet", "ignorechars", NULL};
|
||||
static _PyArg_Parser _parser = {
|
||||
.keywords = _keywords,
|
||||
.fname = "a2b_base64",
|
||||
.kwtuple = KWTUPLE,
|
||||
};
|
||||
#undef KWTUPLE
|
||||
PyObject *argsbuf[3];
|
||||
PyObject *argsbuf[4];
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
|
||||
Py_buffer data = {NULL, NULL};
|
||||
int strict_mode = -1;
|
||||
PyBytesObject *alphabet = NULL;
|
||||
Py_buffer ignorechars = {NULL, NULL};
|
||||
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
|
||||
@@ -194,11 +195,21 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
}
|
||||
if (PyObject_GetBuffer(args[2], &ignorechars, PyBUF_SIMPLE) != 0) {
|
||||
if (args[2]) {
|
||||
if (!PyBytes_Check(args[2])) {
|
||||
_PyArg_BadArgument("a2b_base64", "argument 'alphabet'", "bytes", args[2]);
|
||||
goto exit;
|
||||
}
|
||||
alphabet = (PyBytesObject *)args[2];
|
||||
if (!--noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
}
|
||||
if (PyObject_GetBuffer(args[3], &ignorechars, PyBUF_SIMPLE) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
skip_optional_kwonly:
|
||||
return_value = binascii_a2b_base64_impl(module, &data, strict_mode, &ignorechars);
|
||||
return_value = binascii_a2b_base64_impl(module, &data, strict_mode, alphabet, &ignorechars);
|
||||
|
||||
exit:
|
||||
/* Cleanup for data */
|
||||
@@ -213,7 +224,8 @@ exit:
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(binascii_b2a_base64__doc__,
|
||||
"b2a_base64($module, data, /, *, wrapcol=0, newline=True)\n"
|
||||
"b2a_base64($module, data, /, *, wrapcol=0, newline=True,\n"
|
||||
" alphabet=BASE64_ALPHABET)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Base64-code line of data.");
|
||||
@@ -223,7 +235,7 @@ PyDoc_STRVAR(binascii_b2a_base64__doc__,
|
||||
|
||||
static PyObject *
|
||||
binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol,
|
||||
int newline);
|
||||
int newline, Py_buffer *alphabet);
|
||||
|
||||
static PyObject *
|
||||
binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||
@@ -231,7 +243,7 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
PyObject *return_value = NULL;
|
||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
|
||||
#define NUM_KEYWORDS 2
|
||||
#define NUM_KEYWORDS 3
|
||||
static struct {
|
||||
PyGC_Head _this_is_not_used;
|
||||
PyObject_VAR_HEAD
|
||||
@@ -240,7 +252,7 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
} _kwtuple = {
|
||||
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
|
||||
.ob_hash = -1,
|
||||
.ob_item = { &_Py_ID(wrapcol), &_Py_ID(newline), },
|
||||
.ob_item = { &_Py_ID(wrapcol), &_Py_ID(newline), &_Py_ID(alphabet), },
|
||||
};
|
||||
#undef NUM_KEYWORDS
|
||||
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
|
||||
@@ -249,18 +261,19 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
# define KWTUPLE NULL
|
||||
#endif // !Py_BUILD_CORE
|
||||
|
||||
static const char * const _keywords[] = {"", "wrapcol", "newline", NULL};
|
||||
static const char * const _keywords[] = {"", "wrapcol", "newline", "alphabet", NULL};
|
||||
static _PyArg_Parser _parser = {
|
||||
.keywords = _keywords,
|
||||
.fname = "b2a_base64",
|
||||
.kwtuple = KWTUPLE,
|
||||
};
|
||||
#undef KWTUPLE
|
||||
PyObject *argsbuf[3];
|
||||
PyObject *argsbuf[4];
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
|
||||
Py_buffer data = {NULL, NULL};
|
||||
size_t wrapcol = 0;
|
||||
int newline = 1;
|
||||
Py_buffer alphabet = {NULL, NULL};
|
||||
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
|
||||
/*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
|
||||
@@ -281,18 +294,30 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
}
|
||||
newline = PyObject_IsTrue(args[2]);
|
||||
if (newline < 0) {
|
||||
if (args[2]) {
|
||||
newline = PyObject_IsTrue(args[2]);
|
||||
if (newline < 0) {
|
||||
goto exit;
|
||||
}
|
||||
if (!--noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
}
|
||||
if (PyObject_GetBuffer(args[3], &alphabet, PyBUF_SIMPLE) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
skip_optional_kwonly:
|
||||
return_value = binascii_b2a_base64_impl(module, &data, wrapcol, newline);
|
||||
return_value = binascii_b2a_base64_impl(module, &data, wrapcol, newline, &alphabet);
|
||||
|
||||
exit:
|
||||
/* Cleanup for data */
|
||||
if (data.obj) {
|
||||
PyBuffer_Release(&data);
|
||||
}
|
||||
/* Cleanup for alphabet */
|
||||
if (alphabet.obj) {
|
||||
PyBuffer_Release(&alphabet);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
@@ -519,27 +544,72 @@ exit:
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(binascii_a2b_base85__doc__,
|
||||
"a2b_base85($module, data, /)\n"
|
||||
"a2b_base85($module, data, /, *, alphabet=BASE85_ALPHABET)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Decode a line of Base85 data.");
|
||||
|
||||
#define BINASCII_A2B_BASE85_METHODDEF \
|
||||
{"a2b_base85", (PyCFunction)binascii_a2b_base85, METH_O, binascii_a2b_base85__doc__},
|
||||
{"a2b_base85", _PyCFunction_CAST(binascii_a2b_base85), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base85__doc__},
|
||||
|
||||
static PyObject *
|
||||
binascii_a2b_base85_impl(PyObject *module, Py_buffer *data);
|
||||
binascii_a2b_base85_impl(PyObject *module, Py_buffer *data,
|
||||
PyBytesObject *alphabet);
|
||||
|
||||
static PyObject *
|
||||
binascii_a2b_base85(PyObject *module, PyObject *arg)
|
||||
binascii_a2b_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
Py_buffer data = {NULL, NULL};
|
||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
|
||||
if (!ascii_buffer_converter(arg, &data)) {
|
||||
#define NUM_KEYWORDS 1
|
||||
static struct {
|
||||
PyGC_Head _this_is_not_used;
|
||||
PyObject_VAR_HEAD
|
||||
Py_hash_t ob_hash;
|
||||
PyObject *ob_item[NUM_KEYWORDS];
|
||||
} _kwtuple = {
|
||||
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
|
||||
.ob_hash = -1,
|
||||
.ob_item = { &_Py_ID(alphabet), },
|
||||
};
|
||||
#undef NUM_KEYWORDS
|
||||
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
|
||||
|
||||
#else // !Py_BUILD_CORE
|
||||
# define KWTUPLE NULL
|
||||
#endif // !Py_BUILD_CORE
|
||||
|
||||
static const char * const _keywords[] = {"", "alphabet", NULL};
|
||||
static _PyArg_Parser _parser = {
|
||||
.keywords = _keywords,
|
||||
.fname = "a2b_base85",
|
||||
.kwtuple = KWTUPLE,
|
||||
};
|
||||
#undef KWTUPLE
|
||||
PyObject *argsbuf[2];
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
|
||||
Py_buffer data = {NULL, NULL};
|
||||
PyBytesObject *alphabet = NULL;
|
||||
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
|
||||
/*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
|
||||
if (!args) {
|
||||
goto exit;
|
||||
}
|
||||
return_value = binascii_a2b_base85_impl(module, &data);
|
||||
if (!ascii_buffer_converter(args[0], &data)) {
|
||||
goto exit;
|
||||
}
|
||||
if (!noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
if (!PyBytes_Check(args[1])) {
|
||||
_PyArg_BadArgument("a2b_base85", "argument 'alphabet'", "bytes", args[1]);
|
||||
goto exit;
|
||||
}
|
||||
alphabet = (PyBytesObject *)args[1];
|
||||
skip_optional_kwonly:
|
||||
return_value = binascii_a2b_base85_impl(module, &data, alphabet);
|
||||
|
||||
exit:
|
||||
/* Cleanup for data */
|
||||
@@ -550,7 +620,7 @@ exit:
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(binascii_b2a_base85__doc__,
|
||||
"b2a_base85($module, data, /, *, pad=False)\n"
|
||||
"b2a_base85($module, data, /, *, pad=False, alphabet=BASE85_ALPHABET)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Base85-code line of data.\n"
|
||||
@@ -562,7 +632,8 @@ PyDoc_STRVAR(binascii_b2a_base85__doc__,
|
||||
{"b2a_base85", _PyCFunction_CAST(binascii_b2a_base85), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_base85__doc__},
|
||||
|
||||
static PyObject *
|
||||
binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad);
|
||||
binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad,
|
||||
Py_buffer *alphabet);
|
||||
|
||||
static PyObject *
|
||||
binascii_b2a_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||
@@ -570,7 +641,7 @@ binascii_b2a_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
PyObject *return_value = NULL;
|
||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
|
||||
#define NUM_KEYWORDS 1
|
||||
#define NUM_KEYWORDS 2
|
||||
static struct {
|
||||
PyGC_Head _this_is_not_used;
|
||||
PyObject_VAR_HEAD
|
||||
@@ -579,7 +650,7 @@ binascii_b2a_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
} _kwtuple = {
|
||||
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
|
||||
.ob_hash = -1,
|
||||
.ob_item = { &_Py_ID(pad), },
|
||||
.ob_item = { &_Py_ID(pad), &_Py_ID(alphabet), },
|
||||
};
|
||||
#undef NUM_KEYWORDS
|
||||
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
|
||||
@@ -588,17 +659,18 @@ binascii_b2a_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
# define KWTUPLE NULL
|
||||
#endif // !Py_BUILD_CORE
|
||||
|
||||
static const char * const _keywords[] = {"", "pad", NULL};
|
||||
static const char * const _keywords[] = {"", "pad", "alphabet", NULL};
|
||||
static _PyArg_Parser _parser = {
|
||||
.keywords = _keywords,
|
||||
.fname = "b2a_base85",
|
||||
.kwtuple = KWTUPLE,
|
||||
};
|
||||
#undef KWTUPLE
|
||||
PyObject *argsbuf[2];
|
||||
PyObject *argsbuf[3];
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
|
||||
Py_buffer data = {NULL, NULL};
|
||||
int pad = 0;
|
||||
Py_buffer alphabet = {NULL, NULL};
|
||||
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
|
||||
/*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
|
||||
@@ -611,126 +683,29 @@ binascii_b2a_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||
if (!noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
pad = PyObject_IsTrue(args[1]);
|
||||
if (pad < 0) {
|
||||
if (args[1]) {
|
||||
pad = PyObject_IsTrue(args[1]);
|
||||
if (pad < 0) {
|
||||
goto exit;
|
||||
}
|
||||
if (!--noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
}
|
||||
if (PyObject_GetBuffer(args[2], &alphabet, PyBUF_SIMPLE) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
skip_optional_kwonly:
|
||||
return_value = binascii_b2a_base85_impl(module, &data, pad);
|
||||
return_value = binascii_b2a_base85_impl(module, &data, pad, &alphabet);
|
||||
|
||||
exit:
|
||||
/* Cleanup for data */
|
||||
if (data.obj) {
|
||||
PyBuffer_Release(&data);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(binascii_a2b_z85__doc__,
|
||||
"a2b_z85($module, data, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Decode a line of Z85 data.");
|
||||
|
||||
#define BINASCII_A2B_Z85_METHODDEF \
|
||||
{"a2b_z85", (PyCFunction)binascii_a2b_z85, METH_O, binascii_a2b_z85__doc__},
|
||||
|
||||
static PyObject *
|
||||
binascii_a2b_z85_impl(PyObject *module, Py_buffer *data);
|
||||
|
||||
static PyObject *
|
||||
binascii_a2b_z85(PyObject *module, PyObject *arg)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
Py_buffer data = {NULL, NULL};
|
||||
|
||||
if (!ascii_buffer_converter(arg, &data)) {
|
||||
goto exit;
|
||||
}
|
||||
return_value = binascii_a2b_z85_impl(module, &data);
|
||||
|
||||
exit:
|
||||
/* Cleanup for data */
|
||||
if (data.obj)
|
||||
PyBuffer_Release(&data);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(binascii_b2a_z85__doc__,
|
||||
"b2a_z85($module, data, /, *, pad=False)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Z85-code line of data.\n"
|
||||
"\n"
|
||||
" pad\n"
|
||||
" Pad input to a multiple of 4 before encoding.");
|
||||
|
||||
#define BINASCII_B2A_Z85_METHODDEF \
|
||||
{"b2a_z85", _PyCFunction_CAST(binascii_b2a_z85), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_z85__doc__},
|
||||
|
||||
static PyObject *
|
||||
binascii_b2a_z85_impl(PyObject *module, Py_buffer *data, int pad);
|
||||
|
||||
static PyObject *
|
||||
binascii_b2a_z85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
|
||||
#define NUM_KEYWORDS 1
|
||||
static struct {
|
||||
PyGC_Head _this_is_not_used;
|
||||
PyObject_VAR_HEAD
|
||||
Py_hash_t ob_hash;
|
||||
PyObject *ob_item[NUM_KEYWORDS];
|
||||
} _kwtuple = {
|
||||
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
|
||||
.ob_hash = -1,
|
||||
.ob_item = { &_Py_ID(pad), },
|
||||
};
|
||||
#undef NUM_KEYWORDS
|
||||
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
|
||||
|
||||
#else // !Py_BUILD_CORE
|
||||
# define KWTUPLE NULL
|
||||
#endif // !Py_BUILD_CORE
|
||||
|
||||
static const char * const _keywords[] = {"", "pad", NULL};
|
||||
static _PyArg_Parser _parser = {
|
||||
.keywords = _keywords,
|
||||
.fname = "b2a_z85",
|
||||
.kwtuple = KWTUPLE,
|
||||
};
|
||||
#undef KWTUPLE
|
||||
PyObject *argsbuf[2];
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
|
||||
Py_buffer data = {NULL, NULL};
|
||||
int pad = 0;
|
||||
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
|
||||
/*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
|
||||
if (!args) {
|
||||
goto exit;
|
||||
}
|
||||
if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
if (!noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
pad = PyObject_IsTrue(args[1]);
|
||||
if (pad < 0) {
|
||||
goto exit;
|
||||
}
|
||||
skip_optional_kwonly:
|
||||
return_value = binascii_b2a_z85_impl(module, &data, pad);
|
||||
|
||||
exit:
|
||||
/* Cleanup for data */
|
||||
if (data.obj) {
|
||||
PyBuffer_Release(&data);
|
||||
/* Cleanup for alphabet */
|
||||
if (alphabet.obj) {
|
||||
PyBuffer_Release(&alphabet);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
@@ -1281,4 +1256,4 @@ exit:
|
||||
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=5c53e7e185700742 input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=84c97096b0fb3819 input=a9049054013a1b77]*/
|
||||
|
||||
Reference in New Issue
Block a user