1 /*
2   Unordered Maps
3 */
4 %include <std_map.i>
5 
6 %fragment("StdUnorderedMapForwardIteratorTraits","header")
7 {
8   namespace swig {
9     template<class OutIterator, class FromOper, class ValueType = typename OutIterator::value_type>
10     struct SwigPyMapForwardIterator_T : SwigPyForwardIteratorClosed_T<OutIterator, ValueType, FromOper>
11     {
SwigPyMapForwardIterator_TSwigPyMapForwardIterator_T12       SwigPyMapForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
13 	: SwigPyForwardIteratorClosed_T<OutIterator,ValueType,FromOper>(curr, first, last, seq)
14       {
15       }
16     };
17 
18 
19     template<class OutIterator,
20 	     class FromOper = from_key_oper<typename OutIterator::value_type> >
21     struct SwigPyMapKeyForwardIterator_T : SwigPyMapForwardIterator_T<OutIterator, FromOper>
22     {
SwigPyMapKeyForwardIterator_TSwigPyMapKeyForwardIterator_T23       SwigPyMapKeyForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
24 	: SwigPyMapForwardIterator_T<OutIterator, FromOper>(curr, first, last, seq)
25       {
26       }
27     };
28 
29     template<typename OutIter>
30     inline SwigPyIterator*
31     make_output_key_forward_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0)
32     {
33       return new SwigPyMapKeyForwardIterator_T<OutIter>(current, begin, end, seq);
34     }
35 
36     template<class OutIterator,
37 	     class FromOper = from_value_oper<typename OutIterator::value_type> >
38     struct SwigPyMapValueForwardIterator_T : SwigPyMapForwardIterator_T<OutIterator, FromOper>
39     {
SwigPyMapValueForwardIterator_TSwigPyMapValueForwardIterator_T40       SwigPyMapValueForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
41 	: SwigPyMapForwardIterator_T<OutIterator, FromOper>(curr, first, last, seq)
42       {
43       }
44     };
45 
46 
47     template<typename OutIter>
48     inline SwigPyIterator*
49     make_output_value_forward_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0)
50     {
51       return new SwigPyMapValueForwardIterator_T<OutIter>(current, begin, end, seq);
52     }
53   }
54 }
55 
56 %fragment("StdUnorderedMapTraits","header",fragment="StdMapCommonTraits",fragment="StdUnorderedMapForwardIteratorTraits")
57 {
58   namespace swig {
59     template <class SwigPySeq, class K, class T, class Hash, class Compare, class Alloc>
60     inline void
assign(const SwigPySeq & swigpyseq,std::unordered_map<K,T,Hash,Compare,Alloc> * unordered_map)61     assign(const SwigPySeq& swigpyseq, std::unordered_map<K,T,Hash,Compare,Alloc> *unordered_map) {
62       typedef typename std::unordered_map<K,T,Hash,Compare,Alloc>::value_type value_type;
63       typename SwigPySeq::const_iterator it = swigpyseq.begin();
64       for (;it != swigpyseq.end(); ++it) {
65 	unordered_map->insert(value_type(it->first, it->second));
66       }
67     }
68 
69     template <class K, class T, class Hash, class Compare, class Alloc>
70     struct traits_reserve<std::unordered_map<K,T,Hash,Compare,Alloc> > {
71       static void reserve(std::unordered_map<K,T,Hash,Compare,Alloc> &seq, typename std::unordered_map<K,T,Hash,Compare,Alloc>::size_type n) {
72         seq.reserve(n);
73       }
74     };
75 
76     template <class K, class T, class Hash, class Compare, class Alloc>
77     struct traits_asptr<std::unordered_map<K,T,Hash,Compare,Alloc> >  {
78       typedef std::unordered_map<K,T,Hash,Compare,Alloc> unordered_map_type;
79       static int asptr(PyObject *obj, unordered_map_type **val) {
80 	int res = SWIG_ERROR;
81 	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
82 	if (PyDict_Check(obj)) {
83 	  SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL);
84 %#if PY_VERSION_HEX >= 0x03000000
85           /* In Python 3.x the ".items()" method returns a dict_items object */
86           items = PySequence_Fast(items, ".items() didn't return a sequence!");
87 %#endif
88 	  res = traits_asptr_stdseq<std::unordered_map<K,T,Hash,Compare,Alloc>, std::pair<K, T> >::asptr(items, val);
89 	} else {
90 	  unordered_map_type *p = 0;
91 	  swig_type_info *descriptor = swig::type_info<unordered_map_type>();
92 	  res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR;
93 	  if (SWIG_IsOK(res) && val)  *val = p;
94 	}
95 	SWIG_PYTHON_THREAD_END_BLOCK;
96 	return res;
97       }
98     };
99 
100     template <class K, class T, class Hash, class Compare, class Alloc>
101     struct traits_from<std::unordered_map<K,T,Hash,Compare,Alloc> >  {
102       typedef std::unordered_map<K,T,Hash,Compare,Alloc> unordered_map_type;
103       typedef typename unordered_map_type::const_iterator const_iterator;
104       typedef typename unordered_map_type::size_type size_type;
105 
106       static PyObject *asdict(const unordered_map_type& map) {
107 	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
108 	size_type size = map.size();
109 	Py_ssize_t pysize = (size <= (size_type) INT_MAX) ? (Py_ssize_t) size : -1;
110 	if (pysize < 0) {
111 	  PyErr_SetString(PyExc_OverflowError, "map size not valid in python");
112 	  SWIG_PYTHON_THREAD_END_BLOCK;
113 	  return NULL;
114 	}
115 	PyObject *obj = PyDict_New();
116 	for (const_iterator i= map.begin(); i!= map.end(); ++i) {
117 	  swig::SwigVar_PyObject key = swig::from(i->first);
118 	  swig::SwigVar_PyObject val = swig::from(i->second);
119 	  PyDict_SetItem(obj, key, val);
120 	}
121 	SWIG_PYTHON_THREAD_END_BLOCK;
122 	return obj;
123       }
124 
125       static PyObject *from(const unordered_map_type& map) {
126 	swig_type_info *desc = swig::type_info<unordered_map_type>();
127 	if (desc && desc->clientdata) {
128 	  return SWIG_InternalNewPointerObj(new unordered_map_type(map), desc, SWIG_POINTER_OWN);
129 	} else {
130 	  return asdict(map);
131 	}
132       }
133     };
134   }
135 }
136 
137 %define %swig_unordered_map_common(Map...)
138   %swig_sequence_forward_iterator(Map);
139   %swig_container_methods(Map)
140 
141 #if defined(SWIGPYTHON_BUILTIN)
142   %feature("python:slot", "mp_length", functype="lenfunc") __len__;
143   %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__;
144   %feature("python:slot", "tp_iter", functype="getiterfunc") key_iterator;
145   %feature("python:slot", "sq_contains", functype="objobjproc") __contains__;
146 
147   %extend {
148     %newobject iterkeys(PyObject **PYTHON_SELF);
149     swig::SwigPyIterator* iterkeys(PyObject **PYTHON_SELF) {
150       return swig::make_output_key_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
151     }
152 
153     %newobject itervalues(PyObject **PYTHON_SELF);
154     swig::SwigPyIterator* itervalues(PyObject **PYTHON_SELF) {
155       return swig::make_output_value_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
156     }
157 
158     %newobject iteritems(PyObject **PYTHON_SELF);
159     swig::SwigPyIterator* iteritems(PyObject **PYTHON_SELF) {
160       return swig::make_output_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
161     }
162   }
163 
164 #else
165   %extend {
166     %pythoncode %{def __iter__(self):
167     return self.key_iterator()%}
168     %pythoncode %{def iterkeys(self):
169     return self.key_iterator()%}
170     %pythoncode %{def itervalues(self):
171     return self.value_iterator()%}
172     %pythoncode %{def iteritems(self):
173     return self.iterator()%}
174   }
175 #endif
176 
177   %extend {
178     mapped_type const & __getitem__(const key_type& key) throw (std::out_of_range) {
179       Map::const_iterator i = self->find(key);
180       if (i != self->end())
181 	return i->second;
182       else
183 	throw std::out_of_range("key not found");
184     }
185 
186     void __delitem__(const key_type& key) throw (std::out_of_range) {
187       Map::iterator i = self->find(key);
188       if (i != self->end())
189 	self->erase(i);
190       else
191 	throw std::out_of_range("key not found");
192     }
193 
194     bool has_key(const key_type& key) const {
195       Map::const_iterator i = self->find(key);
196       return i != self->end();
197     }
198 
199     PyObject* keys() {
200       Map::size_type size = self->size();
201       Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1;
202       SWIG_PYTHON_THREAD_BEGIN_BLOCK;
203       if (pysize < 0) {
204 	PyErr_SetString(PyExc_OverflowError, "unordered_map size not valid in python");
205 	SWIG_PYTHON_THREAD_END_BLOCK;
206 	return NULL;
207       }
208       PyObject* keyList = PyList_New(pysize);
209       Map::const_iterator i = self->begin();
210       for (Py_ssize_t j = 0; j < pysize; ++i, ++j) {
211 	PyList_SET_ITEM(keyList, j, swig::from(i->first));
212       }
213       SWIG_PYTHON_THREAD_END_BLOCK;
214       return keyList;
215     }
216 
217     PyObject* values() {
218       Map::size_type size = self->size();
219       Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1;
220       SWIG_PYTHON_THREAD_BEGIN_BLOCK;
221       if (pysize < 0) {
222 	PyErr_SetString(PyExc_OverflowError, "unordered_map size not valid in python");
223 	SWIG_PYTHON_THREAD_END_BLOCK;
224 	return NULL;
225       }
226       PyObject* valList = PyList_New(pysize);
227       Map::const_iterator i = self->begin();
228       for (Py_ssize_t j = 0; j < pysize; ++i, ++j) {
229 	PyList_SET_ITEM(valList, j, swig::from(i->second));
230       }
231       SWIG_PYTHON_THREAD_END_BLOCK;
232       return valList;
233     }
234 
235     PyObject* items() {
236       Map::size_type size = self->size();
237       Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1;
238       SWIG_PYTHON_THREAD_BEGIN_BLOCK;
239       if (pysize < 0) {
240 	PyErr_SetString(PyExc_OverflowError, "unordered_map size not valid in python");
241 	SWIG_PYTHON_THREAD_END_BLOCK;
242 	return NULL;
243       }
244       PyObject* itemList = PyList_New(pysize);
245       Map::const_iterator i = self->begin();
246       for (Py_ssize_t j = 0; j < pysize; ++i, ++j) {
247 	PyList_SET_ITEM(itemList, j, swig::from(*i));
248       }
249       SWIG_PYTHON_THREAD_END_BLOCK;
250       return itemList;
251     }
252 
253     bool __contains__(const key_type& key) {
254       return self->find(key) != self->end();
255     }
256 
257     %newobject key_iterator(PyObject **PYTHON_SELF);
258     swig::SwigPyIterator* key_iterator(PyObject **PYTHON_SELF) {
259       return swig::make_output_key_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
260     }
261 
262     %newobject value_iterator(PyObject **PYTHON_SELF);
263     swig::SwigPyIterator* value_iterator(PyObject **PYTHON_SELF) {
264       return swig::make_output_value_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
265     }
266   }
267 
268 %enddef
269 
270 %define %swig_unordered_map_methods(Map...)
271   %swig_unordered_map_common(Map)
272 
273 #if defined(SWIGPYTHON_BUILTIN)
274   %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__;
275 #endif
276 
277   %extend {
278     // This will be called through the mp_ass_subscript slot to delete an entry.
279     void __setitem__(const key_type& key) {
280       self->erase(key);
281     }
282 
283     void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) {
284       (*self)[key] = x;
285     }
286 
287     PyObject* asdict() {
288       return swig::traits_from< Map >::asdict(*self);
289     }
290   }
291 
292 
293 %enddef
294 
295 
296 %include <std/std_unordered_map.i>
297