/home/mdboom/Work/builds/cpython/Include/internal/pycore_hamt.h
Line | Count | Source |
1 | #ifndef Py_INTERNAL_HAMT_H |
2 | #define Py_INTERNAL_HAMT_H |
3 | |
4 | #ifndef Py_BUILD_CORE |
5 | # error "this header requires Py_BUILD_CORE define" |
6 | #endif |
7 | |
8 | |
9 | /* |
10 | HAMT tree is shaped by hashes of keys. Every group of 5 bits of a hash denotes |
11 | the exact position of the key in one level of the tree. Since we're using |
12 | 32 bit hashes, we can have at most 7 such levels. Although if there are |
13 | two distinct keys with equal hashes, they will have to occupy the same |
14 | cell in the 7th level of the tree -- so we'd put them in a "collision" node. |
15 | Which brings the total possible tree depth to 8. Read more about the actual |
16 | layout of the HAMT tree in `hamt.c`. |
17 | |
18 | This constant is used to define a datastucture for storing iteration state. |
19 | */ |
20 | #define _Py_HAMT_MAX_TREE_DEPTH 8 |
21 | |
22 | |
23 | extern PyTypeObject _PyHamt_Type; |
24 | extern PyTypeObject _PyHamt_ArrayNode_Type; |
25 | extern PyTypeObject _PyHamt_BitmapNode_Type; |
26 | extern PyTypeObject _PyHamt_CollisionNode_Type; |
27 | extern PyTypeObject _PyHamtKeys_Type; |
28 | extern PyTypeObject _PyHamtValues_Type; |
29 | extern PyTypeObject _PyHamtItems_Type; |
30 | |
31 | /* runtime lifecycle */ |
32 | |
33 | void _PyHamt_Fini(PyInterpreterState *); |
34 | |
35 | |
36 | /* other API */ |
37 | |
38 | #define PyHamt_Check(o) Py_IS_TYPE((o), &_PyHamt_Type) |
39 | |
40 | |
41 | /* Abstract tree node. */ |
42 | typedef struct { |
43 | PyObject_HEAD |
44 | } PyHamtNode; |
45 | |
46 | |
47 | /* An HAMT immutable mapping collection. */ |
48 | typedef struct { |
49 | PyObject_HEAD |
50 | PyHamtNode *h_root; |
51 | PyObject *h_weakreflist; |
52 | Py_ssize_t h_count; |
53 | } PyHamtObject; |
54 | |
55 | |
56 | /* A struct to hold the state of depth-first traverse of the tree. |
57 | |
58 | HAMT is an immutable collection. Iterators will hold a strong reference |
59 | to it, and every node in the HAMT has strong references to its children. |
60 | |
61 | So for iterators, we can implement zero allocations and zero reference |
62 | inc/dec depth-first iteration. |
63 | |
64 | - i_nodes: an array of seven pointers to tree nodes |
65 | - i_level: the current node in i_nodes |
66 | - i_pos: an array of positions within nodes in i_nodes. |
67 | */ |
68 | typedef struct { |
69 | PyHamtNode *i_nodes[_Py_HAMT_MAX_TREE_DEPTH]; |
70 | Py_ssize_t i_pos[_Py_HAMT_MAX_TREE_DEPTH]; |
71 | int8_t i_level; |
72 | } PyHamtIteratorState; |
73 | |
74 | |
75 | /* Base iterator object. |
76 | |
77 | Contains the iteration state, a pointer to the HAMT tree, |
78 | and a pointer to the 'yield function'. The latter is a simple |
79 | function that returns a key/value tuple for the 'Items' iterator, |
80 | just a key for the 'Keys' iterator, and a value for the 'Values' |
81 | iterator. |
82 | */ |
83 | typedef struct { |
84 | PyObject_HEAD |
85 | PyHamtObject *hi_obj; |
86 | PyHamtIteratorState hi_iter; |
87 | binaryfunc hi_yield; |
88 | } PyHamtIterator; |
89 | |
90 | |
91 | /* Create a new HAMT immutable mapping. */ |
92 | PyHamtObject * _PyHamt_New(void); |
93 | |
94 | /* Return a new collection based on "o", but with an additional |
95 | key/val pair. */ |
96 | PyHamtObject * _PyHamt_Assoc(PyHamtObject *o, PyObject *key, PyObject *val); |
97 | |
98 | /* Return a new collection based on "o", but without "key". */ |
99 | PyHamtObject * _PyHamt_Without(PyHamtObject *o, PyObject *key); |
100 | |
101 | /* Find "key" in the "o" collection. |
102 | |
103 | Return: |
104 | - -1: An error occurred. |
105 | - 0: "key" wasn't found in "o". |
106 | - 1: "key" is in "o"; "*val" is set to its value (a borrowed ref). |
107 | */ |
108 | int _PyHamt_Find(PyHamtObject *o, PyObject *key, PyObject **val); |
109 | |
110 | /* Check if "v" is equal to "w". |
111 | |
112 | Return: |
113 | - 0: v != w |
114 | - 1: v == w |
115 | - -1: An error occurred. |
116 | */ |
117 | int _PyHamt_Eq(PyHamtObject *v, PyHamtObject *w); |
118 | |
119 | /* Return the size of "o"; equivalent of "len(o)". */ |
120 | Py_ssize_t _PyHamt_Len(PyHamtObject *o); |
121 | |
122 | /* Return a Keys iterator over "o". */ |
123 | PyObject * _PyHamt_NewIterKeys(PyHamtObject *o); |
124 | |
125 | /* Return a Values iterator over "o". */ |
126 | PyObject * _PyHamt_NewIterValues(PyHamtObject *o); |
127 | |
128 | /* Return a Items iterator over "o". */ |
129 | PyObject * _PyHamt_NewIterItems(PyHamtObject *o); |
130 | |
131 | #endif /* !Py_INTERNAL_HAMT_H */ |