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