putil: Switch to new Python 3.13+ public long APIs for BitArray
This commit is contained in:
parent
02bd38820e
commit
b806035c40
|
|
@ -20,6 +20,29 @@
|
||||||
*/
|
*/
|
||||||
void Extension<BitArray>::
|
void Extension<BitArray>::
|
||||||
__init__(PyObject *init_value) {
|
__init__(PyObject *init_value) {
|
||||||
|
#if PY_VERSION_HEX >= 0x030e0000 // Python 3.14
|
||||||
|
BitArray::WordType word = 0;
|
||||||
|
Py_ssize_t result = PyLong_AsNativeBytes(init_value, &word, sizeof(word), Py_ASNATIVEBYTES_LITTLE_ENDIAN | Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE);
|
||||||
|
if (result < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((size_t)result <= sizeof(BitArray::WordType)) {
|
||||||
|
// It fit in a single word
|
||||||
|
_this->_array.clear();
|
||||||
|
if (word != 0) {
|
||||||
|
_this->_array.push_back(word);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Requires multiple words.
|
||||||
|
size_t num_words = ((size_t)result + sizeof(BitArray::WordType) - 1) / sizeof(BitArray::WordType);
|
||||||
|
_this->_array.resize(num_words);
|
||||||
|
|
||||||
|
if (PyLong_AsNativeBytes(init_value, &_this->_array[0], num_words * sizeof(BitArray::WordType), Py_ASNATIVEBYTES_LITTLE_ENDIAN | Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE) <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!PyLong_Check(init_value) || !PyLong_IsNonNegative(init_value)) {
|
if (!PyLong_Check(init_value) || !PyLong_IsNonNegative(init_value)) {
|
||||||
PyErr_SetString(PyExc_ValueError, "BitArray constructor requires a positive integer");
|
PyErr_SetString(PyExc_ValueError, "BitArray constructor requires a positive integer");
|
||||||
return;
|
return;
|
||||||
|
|
@ -38,6 +61,7 @@ __init__(PyObject *init_value) {
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -55,19 +79,34 @@ __getstate__() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_this->_highest_bits == 0) {
|
if (_this->_highest_bits == 0) {
|
||||||
|
#if PY_VERSION_HEX >= 0x030e0000 // Python 3.14
|
||||||
|
return PyLong_FromUnsignedNativeBytes(
|
||||||
|
&_this->_array[0], _this->_array.size() * sizeof(BitArray::WordType),
|
||||||
|
Py_ASNATIVEBYTES_LITTLE_ENDIAN);
|
||||||
|
#else
|
||||||
return _PyLong_FromByteArray(
|
return _PyLong_FromByteArray(
|
||||||
(const unsigned char *)&_this->_array[0],
|
(const unsigned char *)&_this->_array[0],
|
||||||
_this->_array.size() * sizeof(BitArray::WordType),
|
_this->_array.size() * sizeof(BitArray::WordType),
|
||||||
1, 0);
|
1, 0);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// This is an infinite array, so we invert it to make it a finite array and
|
// This is an infinite array, so we invert it to make it a finite array and
|
||||||
// store it as an inverted long.
|
// store it as an inverted long.
|
||||||
BitArray copy(*_this);
|
BitArray copy(*_this);
|
||||||
copy.invert_in_place();
|
copy.invert_in_place();
|
||||||
|
#if PY_VERSION_HEX >= 0x030e0000 // Python 3.14
|
||||||
|
PyObject *state = PyLong_FromUnsignedNativeBytes(
|
||||||
|
©._array[0], copy._array.size() * sizeof(BitArray::WordType),
|
||||||
|
Py_ASNATIVEBYTES_LITTLE_ENDIAN);
|
||||||
|
#else
|
||||||
PyObject *state = _PyLong_FromByteArray(
|
PyObject *state = _PyLong_FromByteArray(
|
||||||
(const unsigned char *)©._array[0],
|
(const unsigned char *)©._array[0],
|
||||||
copy._array.size() * sizeof(BitArray::WordType),
|
copy._array.size() * sizeof(BitArray::WordType),
|
||||||
1, 0);
|
1, 0);
|
||||||
|
#endif
|
||||||
|
if (state == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
PyObject *inverted = PyNumber_Invert(state);
|
PyObject *inverted = PyNumber_Invert(state);
|
||||||
Py_DECREF(state);
|
Py_DECREF(state);
|
||||||
return inverted;
|
return inverted;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,20 @@ def test_bitarray_constructor():
|
||||||
assert BitArray().is_zero()
|
assert BitArray().is_zero()
|
||||||
assert BitArray(0).is_zero()
|
assert BitArray(0).is_zero()
|
||||||
|
|
||||||
|
one = BitArray(1)
|
||||||
|
assert not one.is_zero()
|
||||||
|
assert one.get_lowest_on_bit() == 0
|
||||||
|
assert one.get_highest_on_bit() == 0
|
||||||
|
assert one.get_lowest_off_bit() == 1
|
||||||
|
assert one.get_highest_off_bit() == -1
|
||||||
|
|
||||||
|
two = BitArray(2)
|
||||||
|
assert not two.is_zero()
|
||||||
|
assert two.get_lowest_on_bit() == 1
|
||||||
|
assert two.get_highest_on_bit() == 1
|
||||||
|
assert two.get_lowest_off_bit() == 0
|
||||||
|
assert two.get_highest_off_bit() == -1
|
||||||
|
|
||||||
ba = BitArray(0x10000000000000000000000000)
|
ba = BitArray(0x10000000000000000000000000)
|
||||||
assert ba.get_lowest_on_bit() == 100
|
assert ba.get_lowest_on_bit() == 100
|
||||||
assert ba.get_highest_on_bit() == 100
|
assert ba.get_highest_on_bit() == 100
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue