Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 1 | #ifndef Py_INTERNAL_HAMT_H |
| 2 | #define Py_INTERNAL_HAMT_H |
| 3 | |
| 4 | |
| 5 | #define _Py_HAMT_MAX_TREE_DEPTH 7 |
| 6 | |
| 7 | |
| 8 | #define PyHamt_Check(o) (Py_TYPE(o) == &_PyHamt_Type) |
| 9 | |
| 10 | |
| 11 | /* Abstract tree node. */ |
| 12 | typedef struct { |
| 13 | PyObject_HEAD |
| 14 | } PyHamtNode; |
| 15 | |
| 16 | |
| 17 | /* An HAMT immutable mapping collection. */ |
| 18 | typedef struct { |
| 19 | PyObject_HEAD |
| 20 | PyHamtNode *h_root; |
| 21 | PyObject *h_weakreflist; |
| 22 | Py_ssize_t h_count; |
| 23 | } PyHamtObject; |
| 24 | |
| 25 | |
| 26 | /* A struct to hold the state of depth-first traverse of the tree. |
| 27 | |
| 28 | HAMT is an immutable collection. Iterators will hold a strong reference |
| 29 | to it, and every node in the HAMT has strong references to its children. |
| 30 | |
| 31 | So for iterators, we can implement zero allocations and zero reference |
| 32 | inc/dec depth-first iteration. |
| 33 | |
| 34 | - i_nodes: an array of seven pointers to tree nodes |
| 35 | - i_level: the current node in i_nodes |
| 36 | - i_pos: an array of positions within nodes in i_nodes. |
| 37 | */ |
| 38 | typedef struct { |
| 39 | PyHamtNode *i_nodes[_Py_HAMT_MAX_TREE_DEPTH]; |
| 40 | Py_ssize_t i_pos[_Py_HAMT_MAX_TREE_DEPTH]; |
| 41 | int8_t i_level; |
| 42 | } PyHamtIteratorState; |
| 43 | |
| 44 | |
| 45 | /* Base iterator object. |
| 46 | |
| 47 | Contains the iteration state, a pointer to the HAMT tree, |
| 48 | and a pointer to the 'yield function'. The latter is a simple |
| 49 | function that returns a key/value tuple for the 'Items' iterator, |
| 50 | just a key for the 'Keys' iterator, and a value for the 'Values' |
| 51 | iterator. |
| 52 | */ |
| 53 | typedef struct { |
| 54 | PyObject_HEAD |
| 55 | PyHamtObject *hi_obj; |
| 56 | PyHamtIteratorState hi_iter; |
| 57 | binaryfunc hi_yield; |
| 58 | } PyHamtIterator; |
| 59 | |
| 60 | |
| 61 | PyAPI_DATA(PyTypeObject) _PyHamt_Type; |
| 62 | PyAPI_DATA(PyTypeObject) _PyHamt_ArrayNode_Type; |
| 63 | PyAPI_DATA(PyTypeObject) _PyHamt_BitmapNode_Type; |
| 64 | PyAPI_DATA(PyTypeObject) _PyHamt_CollisionNode_Type; |
| 65 | PyAPI_DATA(PyTypeObject) _PyHamtKeys_Type; |
| 66 | PyAPI_DATA(PyTypeObject) _PyHamtValues_Type; |
| 67 | PyAPI_DATA(PyTypeObject) _PyHamtItems_Type; |
| 68 | |
| 69 | |
| 70 | /* Create a new HAMT immutable mapping. */ |
| 71 | PyHamtObject * _PyHamt_New(void); |
| 72 | |
| 73 | /* Return a new collection based on "o", but with an additional |
| 74 | key/val pair. */ |
| 75 | PyHamtObject * _PyHamt_Assoc(PyHamtObject *o, PyObject *key, PyObject *val); |
| 76 | |
| 77 | /* Return a new collection based on "o", but without "key". */ |
| 78 | PyHamtObject * _PyHamt_Without(PyHamtObject *o, PyObject *key); |
| 79 | |
| 80 | /* Find "key" in the "o" collection. |
| 81 | |
| 82 | Return: |
Miss Islington (bot) | 3295529 | 2018-04-20 14:00:41 -0700 | [diff] [blame] | 83 | - -1: An error occurred. |
Yury Selivanov | f23746a | 2018-01-22 19:11:18 -0500 | [diff] [blame] | 84 | - 0: "key" wasn't found in "o". |
| 85 | - 1: "key" is in "o"; "*val" is set to its value (a borrowed ref). |
| 86 | */ |
| 87 | int _PyHamt_Find(PyHamtObject *o, PyObject *key, PyObject **val); |
| 88 | |
| 89 | /* Check if "v" is equal to "w". |
| 90 | |
| 91 | Return: |
| 92 | - 0: v != w |
| 93 | - 1: v == w |
| 94 | - -1: An error occurred. |
| 95 | */ |
| 96 | int _PyHamt_Eq(PyHamtObject *v, PyHamtObject *w); |
| 97 | |
| 98 | /* Return the size of "o"; equivalent of "len(o)". */ |
| 99 | Py_ssize_t _PyHamt_Len(PyHamtObject *o); |
| 100 | |
| 101 | /* Return a Keys iterator over "o". */ |
| 102 | PyObject * _PyHamt_NewIterKeys(PyHamtObject *o); |
| 103 | |
| 104 | /* Return a Values iterator over "o". */ |
| 105 | PyObject * _PyHamt_NewIterValues(PyHamtObject *o); |
| 106 | |
| 107 | /* Return a Items iterator over "o". */ |
| 108 | PyObject * _PyHamt_NewIterItems(PyHamtObject *o); |
| 109 | |
| 110 | int _PyHamt_Init(void); |
| 111 | void _PyHamt_Fini(void); |
| 112 | |
| 113 | #endif /* !Py_INTERNAL_HAMT_H */ |