|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define BITARRAY_VERSION "2.5.1" |
|
|
|
|
|
#ifdef STDC_HEADERS |
|
|
#include <stddef.h> |
|
|
#else |
|
|
#ifdef HAVE_SYS_TYPES_H |
|
|
#include <sys/types.h> |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if (defined(_MSC_VER) && _MSC_VER < 1900 \ |
|
|
&& !defined(__cplusplus) && !defined(inline)) |
|
|
#define inline __inline |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef Py_UNREACHABLE |
|
|
#define Py_UNREACHABLE() abort() |
|
|
#endif |
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3 |
|
|
#define IS_PY3K |
|
|
#define BYTES_SIZE_FMT "y#" |
|
|
#else |
|
|
|
|
|
#define Py_MIN(x, y) (((x) > (y)) ? (y) : (x)) |
|
|
#define Py_MAX(x, y) (((x) > (y)) ? (x) : (y)) |
|
|
#define PySlice_GetIndicesEx(slice, len, start, stop, step, slicelength) \ |
|
|
PySlice_GetIndicesEx(((PySliceObject *) slice), \ |
|
|
(len), (start), (stop), (step), (slicelength)) |
|
|
#define PyLong_FromLong PyInt_FromLong |
|
|
#define BYTES_SIZE_FMT "s#" |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
PyObject_VAR_HEAD |
|
|
char *ob_item; |
|
|
Py_ssize_t allocated; |
|
|
Py_ssize_t nbits; |
|
|
int endian; |
|
|
int ob_exports; |
|
|
PyObject *weakreflist; |
|
|
Py_buffer *buffer; |
|
|
int readonly; |
|
|
} bitarrayobject; |
|
|
|
|
|
|
|
|
#define ENDIAN_LITTLE 0 |
|
|
#define ENDIAN_BIG 1 |
|
|
|
|
|
#define IS_LE(self) ((self)->endian == ENDIAN_LITTLE) |
|
|
#define IS_BE(self) ((self)->endian == ENDIAN_BIG) |
|
|
|
|
|
|
|
|
#define ENDIAN_STR(endian) ((endian) == ENDIAN_LITTLE ? "little" : "big") |
|
|
|
|
|
|
|
|
#define BYTES(bits) (((bits) + 7) >> 3) |
|
|
|
|
|
|
|
|
#define BITMASK(self, i) (((char) 1) << ((self)->endian == ENDIAN_LITTLE ? \ |
|
|
((i) % 8) : (7 - (i) % 8))) |
|
|
|
|
|
|
|
|
#define assert_nbits(self) assert(BYTES((self)->nbits) == Py_SIZE(self)) |
|
|
|
|
|
|
|
|
#define assert_byte_in_range(self, j) \ |
|
|
assert(self->ob_item && 0 <= (j) && (j) < Py_SIZE(self)) |
|
|
|
|
|
|
|
|
|
|
|
static inline int |
|
|
getbit(bitarrayobject *self, Py_ssize_t i) |
|
|
{ |
|
|
assert_nbits(self); |
|
|
assert(0 <= i && i < self->nbits); |
|
|
return self->ob_item[i >> 3] & BITMASK(self, i) ? 1 : 0; |
|
|
} |
|
|
|
|
|
static inline void |
|
|
setbit(bitarrayobject *self, Py_ssize_t i, int vi) |
|
|
{ |
|
|
char *cp, mask; |
|
|
|
|
|
assert_nbits(self); |
|
|
assert(0 <= i && i < self->nbits); |
|
|
assert(self->readonly == 0); |
|
|
|
|
|
mask = BITMASK(self, i); |
|
|
cp = self->ob_item + (i >> 3); |
|
|
if (vi) |
|
|
*cp |= mask; |
|
|
else |
|
|
*cp &= ~mask; |
|
|
} |
|
|
|
|
|
static const char bitmask_table[2][8] = { |
|
|
{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, |
|
|
{0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, |
|
|
}; |
|
|
|
|
|
|
|
|
static const char ones_table[2][8] = { |
|
|
{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}, |
|
|
{0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}, |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static inline char |
|
|
zeroed_last_byte(bitarrayobject *self) |
|
|
{ |
|
|
const int r = self->nbits % 8; |
|
|
|
|
|
assert(r > 0); |
|
|
assert_nbits(self); |
|
|
return ones_table[IS_BE(self)][r] & self->ob_item[Py_SIZE(self) - 1]; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline int |
|
|
setunused(bitarrayobject *self) |
|
|
{ |
|
|
const int r = self->nbits % 8; |
|
|
|
|
|
if (r == 0) |
|
|
return 0; |
|
|
if (self->readonly == 0) |
|
|
self->ob_item[Py_SIZE(self) - 1] = zeroed_last_byte(self); |
|
|
return 8 - r; |
|
|
} |
|
|
|
|
|
static const unsigned char bitcount_lookup[256] = { |
|
|
#define B2(n) n, n + 1, n + 1, n + 2 |
|
|
#define B4(n) B2(n), B2(n + 1), B2(n + 1), B2(n + 2) |
|
|
#define B6(n) B4(n), B4(n + 1), B4(n + 1), B4(n + 2) |
|
|
B6(0), B6(1), B6(1), B6(2) |
|
|
#undef B2 |
|
|
#undef B4 |
|
|
#undef B6 |
|
|
}; |
|
|
|
|
|
|
|
|
static inline void |
|
|
adjust_index(Py_ssize_t length, Py_ssize_t *i, Py_ssize_t step) |
|
|
{ |
|
|
if (*i < 0) { |
|
|
*i += length; |
|
|
if (*i < 0) |
|
|
*i = (step < 0) ? -1 : 0; |
|
|
} |
|
|
else if (*i >= length) { |
|
|
*i = (step < 0) ? length - 1 : length; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static inline Py_ssize_t |
|
|
adjust_indices(Py_ssize_t length, Py_ssize_t *start, Py_ssize_t *stop, |
|
|
Py_ssize_t step) |
|
|
{ |
|
|
#if PY_VERSION_HEX > 0x03060100 |
|
|
return PySlice_AdjustIndices(length, start, stop, step); |
|
|
#else |
|
|
assert(step != 0); |
|
|
adjust_index(length, start, step); |
|
|
adjust_index(length, stop, step); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (step < 0) { |
|
|
if (*stop < *start) |
|
|
return (*start - *stop - 1) / (-step) + 1; |
|
|
} |
|
|
else { |
|
|
if (*start < *stop) |
|
|
return (*stop - *start - 1) / step + 1; |
|
|
} |
|
|
return 0; |
|
|
#endif |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void |
|
|
adjust_step_positive(Py_ssize_t slicelength, |
|
|
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step) |
|
|
{ |
|
|
if (*step < 0) { |
|
|
*stop = *start + 1; |
|
|
*start = *stop + *step * (slicelength - 1) - 1; |
|
|
*step = -(*step); |
|
|
} |
|
|
assert(*start >= 0 && *stop >= 0 && *step > 0 && slicelength >= 0); |
|
|
|
|
|
assert(slicelength != 0 || *stop <= *start); |
|
|
|
|
|
assert(*step != 1 || slicelength == 0 || *stop - *start == slicelength); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline int |
|
|
pybit_as_int(PyObject *value) |
|
|
{ |
|
|
Py_ssize_t x; |
|
|
|
|
|
x = PyNumber_AsSsize_t(value, NULL); |
|
|
if (x == -1 && PyErr_Occurred()) |
|
|
return -1; |
|
|
|
|
|
if (x < 0 || x > 1) { |
|
|
PyErr_Format(PyExc_ValueError, "bit must be 0 or 1, got %zd", x); |
|
|
return -1; |
|
|
} |
|
|
return (int) x; |
|
|
} |
|
|
|