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