1 /**
2   Mirror _dictobject.h
3   */
4 module deimos.python.dictobject;
5 
6 import deimos.python.pyport;
7 import deimos.python.object;
8 import deimos.python.pythonrun;
9 import core.stdc.stdio;
10 
11 extern(C):
12 // Python-header-file: Include/dictobject.h:
13 
14 /** PyDict_MINSIZE is the minimum size of a dictionary.  This many slots are
15  * allocated directly in the dict object (in the ma_smalltable member).
16  * It must be a power of 2, and at least 4.  8 allows dicts with no more
17  * than 5 active entries to live in ma_smalltable (and so avoid an
18  * additional malloc); instrumentation suggested this suffices for the
19  * majority of dicts (consisting mostly of usually-small instance dicts and
20  * usually-small dicts created to pass keyword arguments).
21  */
22 enum int PyDict_MINSIZE = 8;
23 
24 /// _
25 struct PyDictEntry {
26     /** Cached hash code of me_key.  Note that hash codes are C longs.
27      * We have to use Py_ssize_t instead because dict_popitem() abuses
28      * me_hash to hold a search finger.
29      */
30     version(Python_3_2_Or_Later) {
31         Py_hash_t me_hash;
32     }else version(Python_2_5_Or_Later) {
33         Py_ssize_t me_hash;
34     }else{
35         C_long me_hash;
36     }
37     /// _
38     PyObject* me_key;
39     /// _
40     PyObject* me_value;
41 }
42 
43 /**
44 To ensure the lookup algorithm terminates, there must be at least one Unused
45 slot (NULL key) in the table.
46 The value ma_fill is the number of non-NULL keys (sum of Active and Dummy);
47 ma_used is the number of non-NULL, non-dummy keys (== the number of non-NULL
48 values == the number of Active items).
49 To avoid slowing down lookups on a near-full table, we resize the table when
50 it's two-thirds full.
51 
52 */
53 
54 /// subclass of PyObject
55 version(Python_3_4_Or_Later) {
56     struct PyDictKeysObject {
57         // ??!
58     }
59 
60     struct PyDictObject {
61         mixin PyObject_HEAD;
62         /** number of items in the dictionary */
63         Py_ssize_t ma_used;
64 
65         version(Python_3_6_Or_Later) {
66             /** Dictionary version: globally unique, value change each time 
67               the dictionary is modified */
68             ulong ma_version_tag;
69         }
70         PyDictKeysObject* ma_keys;
71 
72         /** If ma_values is NULL, the table is "combined": 
73           keys and values are stored in ma_keys.
74 
75           If ma_values is not NULL, the table is split:
76           keys are stored in ma_keys and values are stored in ma_values */
77         PyObject** ma_values;
78     }
79 }else{
80     struct PyDictObject{
81         mixin PyObject_HEAD;
82 
83         /// _
84         Py_ssize_t ma_fill;
85         /// _
86         Py_ssize_t ma_used;
87         /** The table contains ma_mask + 1 slots, and that's a power of 2.
88          * We store the mask instead of the size because the mask is more
89          * frequently needed.
90          */
91         Py_ssize_t ma_mask;
92         /** ma_table points to ma_smalltable for small tables, else to
93          * additional malloc'ed memory.  ma_table is never NULL!  This rule
94          * saves repeated runtime null-tests in the workhorse getitem and
95          * setitem calls.
96          */
97         PyDictEntry* ma_table;
98         /// _
99         PyDictEntry* function(PyDictObject* mp, PyObject* key, Py_hash_t hash)
100             ma_lookup;
101         /// _
102         PyDictEntry[PyDict_MINSIZE] ma_smalltable;
103     }
104 }
105 
106 version(Python_3_5_Or_Later) {
107     struct _PyDictViewObject {
108         mixin PyObject_HEAD;
109         PyDictObject* dv_dict;
110     }
111 }
112 
113 /// _
114 mixin(PyAPI_DATA!"PyTypeObject PyDict_Type");
115 version(Python_2_7_Or_Later) {
116     /// Availability: >= 2.7
117     mixin(PyAPI_DATA!"PyTypeObject PyDictIterKey_Type");
118     /// Availability: >= 2.7
119     mixin(PyAPI_DATA!"PyTypeObject PyDictIterValue_Type");
120     /// Availability: >= 2.7
121     mixin(PyAPI_DATA!"PyTypeObject PyDictIterItem_Type");
122     /// Availability: >= 2.7
123     mixin(PyAPI_DATA!"PyTypeObject PyDictKeys_Type");
124     /// Availability: >= 2.7
125     mixin(PyAPI_DATA!"PyTypeObject PyDictItems_Type");
126     /// Availability: >= 2.7
127     mixin(PyAPI_DATA!"PyTypeObject PyDictValues_Type");
128 }
129 
130 // D translation of C macro:
131 /// _
132 int PyDict_Check()(PyObject* op) {
133     return PyObject_TypeCheck(op, &PyDict_Type);
134 }
135 // D translation of C macro:
136 /// _
137 int PyDict_CheckExact()(PyObject* op) {
138     return Py_TYPE(op) == &PyDict_Type;
139 }
140 
141 version(Python_2_7_Or_Later) {
142     /// Availability: >= 2.7
143     int PyDictKeys_Check()(PyObject* op) {
144         return Py_TYPE(op) == &PyDictKeys_Type;
145     }
146     /// Availability: >= 2.7
147     int PyDictItems_Check()(PyObject* op) {
148         return Py_TYPE(op) == &PyDictItems_Type;
149     }
150     /// Availability: >= 2.7
151     int PyDictValues_Check()(PyObject* op) {
152         return Py_TYPE(op) == &PyDictValues_Type;
153     }
154     /// Availability: >= 2.7
155     int PyDictViewSet_Check()(PyObject* op) {
156         return PyDictKeys_Check(op) || PyDictItems_Check(op);
157     }
158 }
159 
160 /// _
161 PyObject* PyDict_New();
162 /// _
163 PyObject_BorrowedRef* PyDict_GetItem(PyObject* mp, PyObject* key);
164 version(Python_3_0_Or_Later) {
165     /// Availability: 3.*
166     Borrowed!PyObject* PyDict_GetItemWithError(PyObject* mp, PyObject* key);
167 }
168 /// _
169 int PyDict_SetItem(PyObject* mp, PyObject* key, PyObject* item);
170 /// _
171 int PyDict_DelItem(PyObject* mp, PyObject* key);
172 /// _
173 void PyDict_Clear(PyObject* mp);
174 /// _
175 int PyDict_Next(PyObject* mp, Py_ssize_t* pos, PyObject_BorrowedRef** key, PyObject_BorrowedRef** value);
176 version(Python_2_5_Or_Later) {
177     /// Availability: >= 2.5
178     int _PyDict_Next(
179             PyObject* mp, Py_ssize_t* pos, Borrowed!PyObject** key,
180             Borrowed!PyObject** value, Py_hash_t* hash);
181 }
182 /// _
183 PyObject* PyDict_Keys(PyObject* mp);
184 /// _
185 PyObject* PyDict_Values(PyObject* mp);
186 /// _
187 PyObject* PyDict_Items(PyObject* mp);
188 /// _
189 Py_ssize_t PyDict_Size(PyObject* mp);
190 /// _
191 PyObject* PyDict_Copy(PyObject* mp);
192 /// _
193 int PyDict_Contains(PyObject* mp, PyObject* key);
194 version(Python_2_5_Or_Later) {
195     /// Availability: >= 2.5
196     int _PyDict_Contains(PyObject* mp, PyObject* key, Py_hash_t* hash);
197 }
198 version(Python_2_6_Or_Later) {
199     /// Availability: >= 2.6
200     PyObject* _PyDict_NewPresized(Py_ssize_t minused);
201 }
202 version(Python_2_7_Or_Later) {
203     /// Availability: >= 2.7
204     void _PyDict_MaybeUntrack(PyObject* mp);
205 }
206 version(Python_3_0_Or_Later) {
207     /// Availability: 3.*
208     int _PyDict_HasOnlyStringKeys(PyObject* mp);
209 }
210 
211 /** PyDict_Update(mp, other) is equivalent to PyDict_Merge(mp, other, 1). */
212 int PyDict_Update(PyObject* mp, PyObject* other);
213 /** PyDict_Merge updates/merges from a mapping object (an object that
214    supports PyMapping_Keys() and PyObject_GetItem()).  If override is true,
215    the last occurrence of a key wins, else the first.  The Python
216    dict.update(other) is equivalent to PyDict_Merge(dict, other, 1).
217 */
218 int PyDict_Merge(PyObject* mp, PyObject* other, int override_);
219 /** PyDict_MergeFromSeq2 updates/merges from an iterable object producing
220    iterable objects of length 2.  If override is true, the last occurrence
221    of a key wins, else the first.  The Python dict constructor dict(seq2)
222    is equivalent to dict={}; PyDict_MergeFromSeq(dict, seq2, 1).
223 */
224 int PyDict_MergeFromSeq2(PyObject* d, PyObject* seq2, int override_);
225 
226 /// _
227 PyObject_BorrowedRef* PyDict_GetItemString(PyObject* dp, const(char)* key);
228 /// _
229 int PyDict_SetItemString(PyObject* dp, const(char)* key, PyObject* item);
230 /// _
231 int PyDict_DelItemString(PyObject* dp, const(char)* key);
232 version(Python_2_7_Or_Later) {
233     /// Availability: >= 2.7
234     void _PyDict_DebugMallocStats(FILE* out_);
235 }
236