#include "Python.h"
#include "pycore_bitutils.h"
#include "pycore_hamt.h"
#include "pycore_initconfig.h"
#include "pycore_long.h"
#include "pycore_object.h"
#include <stddef.h>
#define IS_ARRAY_NODE(node) …
#define IS_BITMAP_NODE(node) …
#define IS_COLLISION_NODE(node) …
hamt_find_t;
hamt_without_t;
hamt_iter_t;
#define HAMT_ARRAY_NODE_SIZE …
PyHamtNode_Array;
PyHamtNode_Collision;
static PyHamtObject *
hamt_alloc(void);
static PyHamtNode *
hamt_node_assoc(PyHamtNode *node,
uint32_t shift, int32_t hash,
PyObject *key, PyObject *val, int* added_leaf);
static hamt_without_t
hamt_node_without(PyHamtNode *node,
uint32_t shift, int32_t hash,
PyObject *key,
PyHamtNode **new_node);
static hamt_find_t
hamt_node_find(PyHamtNode *node,
uint32_t shift, int32_t hash,
PyObject *key, PyObject **val);
#ifdef Py_DEBUG
static int
hamt_node_dump(PyHamtNode *node,
PyUnicodeWriter *writer, int level);
#endif
static PyHamtNode *
hamt_node_array_new(Py_ssize_t);
static PyHamtNode *
hamt_node_collision_new(int32_t hash, Py_ssize_t size);
static inline Py_ssize_t
hamt_node_collision_count(PyHamtNode_Collision *node);
#ifdef Py_DEBUG
static void
_hamt_node_array_validate(void *obj_raw)
{
PyObject *obj = _PyObject_CAST(obj_raw);
assert(IS_ARRAY_NODE(obj));
PyHamtNode_Array *node = (PyHamtNode_Array*)obj;
Py_ssize_t i = 0, count = 0;
for (; i < HAMT_ARRAY_NODE_SIZE; i++) {
if (node->a_array[i] != NULL) {
count++;
}
}
assert(count == node->a_count);
}
#define VALIDATE_ARRAY_NODE …
#else
#define VALIDATE_ARRAY_NODE(NODE) …
#endif
static inline int32_t
hamt_hash(PyObject *o)
{ … }
static inline uint32_t
hamt_mask(int32_t hash, uint32_t shift)
{ … }
static inline uint32_t
hamt_bitpos(int32_t hash, uint32_t shift)
{ … }
static inline uint32_t
hamt_bitindex(uint32_t bitmap, uint32_t bit)
{ … }
#ifdef Py_DEBUG
static int
_hamt_dump_ident(PyUnicodeWriter *writer, int level)
{
PyObject *str = NULL;
PyObject *num = NULL;
PyObject *res = NULL;
int ret = -1;
str = PyUnicode_FromString(" ");
if (str == NULL) {
goto error;
}
num = PyLong_FromLong((long)level);
if (num == NULL) {
goto error;
}
res = PyNumber_Multiply(str, num);
if (res == NULL) {
goto error;
}
ret = PyUnicodeWriter_WriteStr(writer, res);
error:
Py_XDECREF(res);
Py_XDECREF(str);
Py_XDECREF(num);
return ret;
}
#endif
static PyHamtNode *
hamt_node_bitmap_new(Py_ssize_t size)
{ … }
static inline Py_ssize_t
hamt_node_bitmap_count(PyHamtNode_Bitmap *node)
{ … }
static PyHamtNode_Bitmap *
hamt_node_bitmap_clone(PyHamtNode_Bitmap *node)
{ … }
static PyHamtNode_Bitmap *
hamt_node_bitmap_clone_without(PyHamtNode_Bitmap *o, uint32_t bit)
{ … }
static PyHamtNode *
hamt_node_new_bitmap_or_collision(uint32_t shift,
PyObject *key1, PyObject *val1,
int32_t key2_hash,
PyObject *key2, PyObject *val2)
{ … }
static PyHamtNode *
hamt_node_bitmap_assoc(PyHamtNode_Bitmap *self,
uint32_t shift, int32_t hash,
PyObject *key, PyObject *val, int* added_leaf)
{ … }
static hamt_without_t
hamt_node_bitmap_without(PyHamtNode_Bitmap *self,
uint32_t shift, int32_t hash,
PyObject *key,
PyHamtNode **new_node)
{ … }
static hamt_find_t
hamt_node_bitmap_find(PyHamtNode_Bitmap *self,
uint32_t shift, int32_t hash,
PyObject *key, PyObject **val)
{ … }
static int
hamt_node_bitmap_traverse(PyHamtNode_Bitmap *self, visitproc visit, void *arg)
{ … }
static void
hamt_node_bitmap_dealloc(PyHamtNode_Bitmap *self)
{ … }
#ifdef Py_DEBUG
static int
hamt_node_bitmap_dump(PyHamtNode_Bitmap *node,
PyUnicodeWriter *writer, int level)
{
Py_ssize_t i;
PyObject *tmp1;
PyObject *tmp2;
if (_hamt_dump_ident(writer, level + 1)) {
goto error;
}
if (PyUnicodeWriter_Format(writer, "BitmapNode(size=%zd count=%zd ",
Py_SIZE(node), Py_SIZE(node) / 2) < 0)
{
goto error;
}
tmp1 = PyLong_FromUnsignedLong(node->b_bitmap);
if (tmp1 == NULL) {
goto error;
}
tmp2 = _PyLong_Format(tmp1, 2);
Py_DECREF(tmp1);
if (tmp2 == NULL) {
goto error;
}
if (PyUnicodeWriter_Format(writer, "bitmap=%S id=%p):\n",
tmp2, node) < 0)
{
Py_DECREF(tmp2);
goto error;
}
Py_DECREF(tmp2);
for (i = 0; i < Py_SIZE(node); i += 2) {
PyObject *key_or_null = node->b_array[i];
PyObject *val_or_node = node->b_array[i + 1];
if (_hamt_dump_ident(writer, level + 2)) {
goto error;
}
if (key_or_null == NULL) {
if (PyUnicodeWriter_WriteUTF8(writer, "NULL:\n", -1) < 0) {
goto error;
}
if (hamt_node_dump((PyHamtNode *)val_or_node,
writer, level + 2))
{
goto error;
}
}
else {
if (PyUnicodeWriter_Format(writer, "%R: %R",
key_or_null, val_or_node) < 0)
{
goto error;
}
}
if (PyUnicodeWriter_WriteUTF8(writer, "\n", 1) < 0) {
goto error;
}
}
return 0;
error:
return -1;
}
#endif
static PyHamtNode *
hamt_node_collision_new(int32_t hash, Py_ssize_t size)
{ … }
static hamt_find_t
hamt_node_collision_find_index(PyHamtNode_Collision *self, PyObject *key,
Py_ssize_t *idx)
{ … }
static PyHamtNode *
hamt_node_collision_assoc(PyHamtNode_Collision *self,
uint32_t shift, int32_t hash,
PyObject *key, PyObject *val, int* added_leaf)
{ … }
static inline Py_ssize_t
hamt_node_collision_count(PyHamtNode_Collision *node)
{ … }
static hamt_without_t
hamt_node_collision_without(PyHamtNode_Collision *self,
uint32_t shift, int32_t hash,
PyObject *key,
PyHamtNode **new_node)
{ … }
static hamt_find_t
hamt_node_collision_find(PyHamtNode_Collision *self,
uint32_t shift, int32_t hash,
PyObject *key, PyObject **val)
{ … }
static int
hamt_node_collision_traverse(PyHamtNode_Collision *self,
visitproc visit, void *arg)
{ … }
static void
hamt_node_collision_dealloc(PyHamtNode_Collision *self)
{ … }
#ifdef Py_DEBUG
static int
hamt_node_collision_dump(PyHamtNode_Collision *node,
PyUnicodeWriter *writer, int level)
{
Py_ssize_t i;
if (_hamt_dump_ident(writer, level + 1)) {
goto error;
}
if (PyUnicodeWriter_Format(writer, "CollisionNode(size=%zd id=%p):\n",
Py_SIZE(node), node) < 0)
{
goto error;
}
for (i = 0; i < Py_SIZE(node); i += 2) {
PyObject *key = node->c_array[i];
PyObject *val = node->c_array[i + 1];
if (_hamt_dump_ident(writer, level + 2)) {
goto error;
}
if (PyUnicodeWriter_Format(writer, "%R: %R\n", key, val) < 0) {
goto error;
}
}
return 0;
error:
return -1;
}
#endif
static PyHamtNode *
hamt_node_array_new(Py_ssize_t count)
{ … }
static PyHamtNode_Array *
hamt_node_array_clone(PyHamtNode_Array *node)
{ … }
static PyHamtNode *
hamt_node_array_assoc(PyHamtNode_Array *self,
uint32_t shift, int32_t hash,
PyObject *key, PyObject *val, int* added_leaf)
{ … }
static hamt_without_t
hamt_node_array_without(PyHamtNode_Array *self,
uint32_t shift, int32_t hash,
PyObject *key,
PyHamtNode **new_node)
{ … }
static hamt_find_t
hamt_node_array_find(PyHamtNode_Array *self,
uint32_t shift, int32_t hash,
PyObject *key, PyObject **val)
{ … }
static int
hamt_node_array_traverse(PyHamtNode_Array *self,
visitproc visit, void *arg)
{ … }
static void
hamt_node_array_dealloc(PyHamtNode_Array *self)
{ … }
#ifdef Py_DEBUG
static int
hamt_node_array_dump(PyHamtNode_Array *node,
PyUnicodeWriter *writer, int level)
{
Py_ssize_t i;
if (_hamt_dump_ident(writer, level + 1)) {
goto error;
}
if (PyUnicodeWriter_Format(writer, "ArrayNode(id=%p):\n", node) < 0) {
goto error;
}
for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {
if (node->a_array[i] == NULL) {
continue;
}
if (_hamt_dump_ident(writer, level + 2)) {
goto error;
}
if (PyUnicodeWriter_Format(writer, "%zd::\n", i) < 0) {
goto error;
}
if (hamt_node_dump(node->a_array[i], writer, level + 1)) {
goto error;
}
if (PyUnicodeWriter_WriteUTF8(writer, "\n", 1) < 0) {
goto error;
}
}
return 0;
error:
return -1;
}
#endif
static PyHamtNode *
hamt_node_assoc(PyHamtNode *node,
uint32_t shift, int32_t hash,
PyObject *key, PyObject *val, int* added_leaf)
{ … }
static hamt_without_t
hamt_node_without(PyHamtNode *node,
uint32_t shift, int32_t hash,
PyObject *key,
PyHamtNode **new_node)
{ … }
static hamt_find_t
hamt_node_find(PyHamtNode *node,
uint32_t shift, int32_t hash,
PyObject *key, PyObject **val)
{ … }
#ifdef Py_DEBUG
static int
hamt_node_dump(PyHamtNode *node,
PyUnicodeWriter *writer, int level)
{
if (IS_BITMAP_NODE(node)) {
return hamt_node_bitmap_dump(
(PyHamtNode_Bitmap *)node, writer, level);
}
else if (IS_ARRAY_NODE(node)) {
return hamt_node_array_dump(
(PyHamtNode_Array *)node, writer, level);
}
else {
assert(IS_COLLISION_NODE(node));
return hamt_node_collision_dump(
(PyHamtNode_Collision *)node, writer, level);
}
}
#endif
static hamt_iter_t
hamt_iterator_next(PyHamtIteratorState *iter, PyObject **key, PyObject **val);
static void
hamt_iterator_init(PyHamtIteratorState *iter, PyHamtNode *root)
{ … }
static hamt_iter_t
hamt_iterator_bitmap_next(PyHamtIteratorState *iter,
PyObject **key, PyObject **val)
{ … }
static hamt_iter_t
hamt_iterator_collision_next(PyHamtIteratorState *iter,
PyObject **key, PyObject **val)
{ … }
static hamt_iter_t
hamt_iterator_array_next(PyHamtIteratorState *iter,
PyObject **key, PyObject **val)
{ … }
static hamt_iter_t
hamt_iterator_next(PyHamtIteratorState *iter, PyObject **key, PyObject **val)
{ … }
PyHamtObject *
_PyHamt_Assoc(PyHamtObject *o, PyObject *key, PyObject *val)
{ … }
PyHamtObject *
_PyHamt_Without(PyHamtObject *o, PyObject *key)
{ … }
static hamt_find_t
hamt_find(PyHamtObject *o, PyObject *key, PyObject **val)
{ … }
int
_PyHamt_Find(PyHamtObject *o, PyObject *key, PyObject **val)
{ … }
int
_PyHamt_Eq(PyHamtObject *v, PyHamtObject *w)
{ … }
Py_ssize_t
_PyHamt_Len(PyHamtObject *o)
{ … }
static PyHamtObject *
hamt_alloc(void)
{ … }
#define _empty_hamt …
PyHamtObject *
_PyHamt_New(void)
{ … }
#ifdef Py_DEBUG
static PyObject *
hamt_dump(PyHamtObject *self)
{
PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
if (writer == NULL) {
return NULL;
}
if (PyUnicodeWriter_Format(writer, "HAMT(len=%zd):\n",
self->h_count) < 0) {
goto error;
}
if (hamt_node_dump(self->h_root, writer, 0)) {
goto error;
}
return PyUnicodeWriter_Finish(writer);
error:
PyUnicodeWriter_Discard(writer);
return NULL;
}
#endif
static int
hamt_baseiter_tp_clear(PyHamtIterator *it)
{ … }
static void
hamt_baseiter_tp_dealloc(PyHamtIterator *it)
{ … }
static int
hamt_baseiter_tp_traverse(PyHamtIterator *it, visitproc visit, void *arg)
{ … }
static PyObject *
hamt_baseiter_tp_iternext(PyHamtIterator *it)
{ … }
static Py_ssize_t
hamt_baseiter_tp_len(PyHamtIterator *it)
{ … }
static PyMappingMethods PyHamtIterator_as_mapping = …;
static PyObject *
hamt_baseiter_new(PyTypeObject *type, binaryfunc yield, PyHamtObject *o)
{ … }
#define ITERATOR_TYPE_SHARED_SLOTS …
PyTypeObject _PyHamtItems_Type = …;
static PyObject *
hamt_iter_yield_items(PyObject *key, PyObject *val)
{ … }
PyObject *
_PyHamt_NewIterItems(PyHamtObject *o)
{ … }
PyTypeObject _PyHamtKeys_Type = …;
static PyObject *
hamt_iter_yield_keys(PyObject *key, PyObject *val)
{ … }
PyObject *
_PyHamt_NewIterKeys(PyHamtObject *o)
{ … }
PyTypeObject _PyHamtValues_Type = …;
static PyObject *
hamt_iter_yield_values(PyObject *key, PyObject *val)
{ … }
PyObject *
_PyHamt_NewIterValues(PyHamtObject *o)
{ … }
#ifdef Py_DEBUG
static PyObject *
hamt_dump(PyHamtObject *self);
#endif
static PyObject *
hamt_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ … }
static int
hamt_tp_clear(PyHamtObject *self)
{ … }
static int
hamt_tp_traverse(PyHamtObject *self, visitproc visit, void *arg)
{ … }
static void
hamt_tp_dealloc(PyHamtObject *self)
{ … }
static PyObject *
hamt_tp_richcompare(PyObject *v, PyObject *w, int op)
{ … }
static int
hamt_tp_contains(PyHamtObject *self, PyObject *key)
{ … }
static PyObject *
hamt_tp_subscript(PyHamtObject *self, PyObject *key)
{ … }
static Py_ssize_t
hamt_tp_len(PyHamtObject *self)
{ … }
static PyObject *
hamt_tp_iter(PyHamtObject *self)
{ … }
static PyObject *
hamt_py_set(PyHamtObject *self, PyObject *args)
{ … }
static PyObject *
hamt_py_get(PyHamtObject *self, PyObject *args)
{ … }
static PyObject *
hamt_py_delete(PyHamtObject *self, PyObject *key)
{ … }
static PyObject *
hamt_py_items(PyHamtObject *self, PyObject *args)
{ … }
static PyObject *
hamt_py_values(PyHamtObject *self, PyObject *args)
{ … }
static PyObject *
hamt_py_keys(PyHamtObject *self, PyObject *Py_UNUSED(args))
{ … }
#ifdef Py_DEBUG
static PyObject *
hamt_py_dump(PyHamtObject *self, PyObject *Py_UNUSED(args))
{
return hamt_dump(self);
}
#endif
static PyMethodDef PyHamt_methods[] = …;
static PySequenceMethods PyHamt_as_sequence = …;
static PyMappingMethods PyHamt_as_mapping = …;
PyTypeObject _PyHamt_Type = …;
PyTypeObject _PyHamt_ArrayNode_Type = …;
PyTypeObject _PyHamt_BitmapNode_Type = …;
PyTypeObject _PyHamt_CollisionNode_Type = …;