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