f19846e88b9f85a0b25f79e8380be136277d6e75
[alexxy/gromacs.git] / src / python / sip / vector.sip
1 // SIP support for std::vector
2 // by Giovanni Bajo <rasky <at> develer.com>
3 // Public domain
4
5 // ****************************************************
6 // SIP generic implementation for std::vector<>
7 // ****************************************************
8 // ALas, this template-based generic implementation is valid only
9 // if the element type is a SIP-wrapped type. For basic types (int, double, etc.)
10 // we are forced to cut & paste to provide a specialization.
11
12 template<TYPE*>
13 %MappedType std::vector<TYPE*>
14 {
15 %TypeHeaderCode
16 #include <vector>
17 %End
18
19 %ConvertFromTypeCode
20     PyObject *l = PyList_New(sipCpp -> size());
21
22     // Create the Python list of the correct length.
23     if (!l)
24         return NULL;
25
26     // Go through each element in the C++ instance and convert it to a
27     // wrapped P2d.
28     for (int i = 0; i < (int)sipCpp->size(); ++i) {
29         TYPE *cpp = sipCpp->at(i);
30         PyObject *pobj = sipConvertFromInstance(cpp, sipClass_TYPE, sipTransferObj);
31
32         // Get the Python wrapper for the Type instance, creating a new
33         // one if necessary, and handle any ownership transfer.
34         if (!pobj) {
35             // There was an error so garbage collect the Python list.
36             Py_DECREF(l);
37             return NULL;
38         }
39
40         // Add the wrapper to the list.
41         PyList_SET_ITEM(l, i, pobj);
42     }
43
44     // Return the Python list.
45     return l;
46 %End
47
48 %ConvertToTypeCode
49     // Check if type is compatible
50     if (!sipIsErr) {
51         // Must be any iterable
52         PyObject *i = PyObject_GetIter(sipPy);
53         bool iterable = (i != NULL);
54         Py_XDECREF(i);
55         return iterable;
56     }
57
58     // Iterate over the object
59     PyObject *iterator = PyObject_GetIter(sipPy);
60     PyObject *item;
61
62     std::vector<TYPE*> *V = new std::vector<TYPE*>();
63
64     while ((item = PyIter_Next(iterator)))
65     {
66         if (!sipCanConvertToInstance(item, sipClass_TYPE, SIP_NOT_NONE)) {
67             PyErr_Format(PyExc_TypeError, "object in iterable cannot be converted to TYPE");
68             *sipIsErr = 1;
69             break;
70         }
71
72         int state;
73         TYPE* p = reinterpret_cast<TYPE*>(
74              sipConvertToInstance(item, sipClass_TYPE, 0, SIP_NOT_NONE, &state, sipIsErr));
75
76         if (!*sipIsErr)
77             V->push_back(p);
78
79         sipReleaseInstance(p, sipClass_TYPE, state);
80         Py_DECREF(item);
81     }
82
83     Py_DECREF(iterator);
84
85     if (*sipIsErr) {
86         delete V;
87         return 0;
88     }
89
90     *sipCppPtr = V;
91     return sipGetState(sipTransferObj);
92 %End
93 };
94
95 // ****************************************************
96 // Specialization for std::vector<char*>
97 // ****************************************************
98
99 %MappedType std::vector<char*>
100 {
101 %TypeHeaderCode
102 #include <vector>
103 %End
104
105 %ConvertFromTypeCode
106     PyObject *l;
107
108     // Create the Python list of the correct length.
109     if ((l = PyList_New(sipCpp -> size())) == NULL)
110         return NULL;
111
112     // Go through each element in the C++ instance and convert it to a
113     // wrapped object.
114     for (int i = 0; i < (int)sipCpp -> size(); ++i)
115     {
116         // Add the wrapper to the list.
117         PyList_SET_ITEM(l, i, sipBuildResult(NULL, "A", sipCpp->at(i)));
118     }
119
120     // Return the Python list.
121     return l;
122 %End
123
124 %ConvertToTypeCode
125     // Check if type is compatible
126     if (sipIsErr == NULL)
127     {
128         // Must be any iterable
129         PyObject *i = PyObject_GetIter(sipPy);
130         bool iterable = (i != NULL);
131         Py_XDECREF(i);
132         return iterable;
133     }
134
135     // Iterate over the object
136     PyObject *iterator = PyObject_GetIter(sipPy);
137     PyObject *item;
138
139     // Maximum number of elements
140     int len = PyObject_Size(sipPy);
141     std::vector<char*> *V = new std::vector<char*>();
142     V->reserve(len);
143
144     if (len)
145     {
146         while ((item = PyIter_Next(iterator)))
147         {
148             if (!PyUnicode_Check(item))
149             {
150                 PyErr_Format(PyExc_TypeError, "object in iterable is not a string");
151                 *sipIsErr = 1;
152                 break;
153             }
154             //FIXME: memory leak here
155             const char* str = strdup(sipString_AsLatin1String(&item));
156
157             V->push_back(const_cast<char*>(str));
158
159             Py_DECREF(item);
160         }
161
162         Py_DECREF(iterator);
163
164         if (*sipIsErr)
165         {
166             delete V;
167             return 0;
168         }
169     }
170
171     *sipCppPtr = V;
172     return sipGetState(sipTransferObj);
173 %End
174 };
175
176 /*
177 // ****************************************************
178 // Specialization for std::vector<double>
179 // ****************************************************
180
181 %MappedType std::vector<double>
182 {
183 %TypeHeaderCode
184 #include <vector>
185 %End
186
187 %ConvertFromTypeCode
188     PyObject *l;
189
190     // Create the Python list of the correct length.
191     if ((l = PyList_New(sipCpp -> size())) == NULL)
192         return NULL;
193
194     // Go through each element in the C++ instance and convert it to a
195     // wrapped object.
196     for (int i = 0; i < (int)sipCpp -> size(); ++i)
197     {
198         // Add the wrapper to the list.
199         PyList_SET_ITEM(l, i, PyFloat_FromDouble(sipCpp -> at(i)));
200     }
201
202     // Return the Python list.
203     return l;
204 %End
205
206 %ConvertToTypeCode
207     // Check if type is compatible
208     if (sipIsErr == NULL)
209     {
210         // Must be any iterable
211         PyObject *i = PyObject_GetIter(sipPy);
212         bool iterable = (i != NULL);
213         Py_XDECREF(i);
214         return iterable;
215     }
216
217     // Iterate over the object
218     PyObject *iterator = PyObject_GetIter(sipPy);
219     PyObject *item;
220
221     // Maximum number of elements
222     int len = PyObject_Size(sipPy);
223     std::vector<double> *V = new std::vector<double>();
224     V->reserve(len);
225
226     if (len)
227     {
228         while ((item = PyIter_Next(iterator)))
229         {
230             if (!PyNumber_Check(item))
231             {
232                 PyErr_Format(PyExc_TypeError, "object in iterable is not a number");
233                 *sipIsErr = 1;
234                 break;
235             }
236
237             PyObject *f = PyNumber_Float(item);
238             V->push_back(PyFloat_AsDouble(f));
239
240             Py_DECREF(f);
241             Py_DECREF(item);
242         }
243
244         Py_DECREF(iterator);
245
246         if (*sipIsErr)
247         {
248             delete V;
249             return 0;
250         }
251     }
252
253     *sipCppPtr = V;
254     return sipGetState(sipTransferObj);
255 %End
256 };
257
258 // ****************************************************
259 // Specialization for std::vector<int>
260 // ****************************************************
261
262 %MappedType std::vector<int>
263 {
264 %TypeHeaderCode
265 #include <vector>
266 %End
267
268 %ConvertFromTypeCode
269     PyObject *l;
270
271     // Create the Python list of the correct length.
272     if ((l = PyList_New((SIP_SSIZE_T)sipCpp -> size())) == NULL)
273         return NULL;
274
275     // Go through each element in the C++ instance and convert it to a
276     // wrapped object.
277     for (int i = 0; i < (int)sipCpp -> size(); ++i)
278     {
279         // Add the wrapper to the list.
280         PyList_SET_ITEM(l, i, PyInt_FromLong(sipCpp -> at(i)));
281     }
282
283     // Return the Python list.
284     return l;
285 %End
286
287 %ConvertToTypeCode
288     // Check if type is compatible
289     if (sipIsErr == NULL)
290     {
291         // Must be any iterable
292         PyObject *i = PyObject_GetIter(sipPy);
293         bool iterable = (i != NULL);
294         Py_XDECREF(i);
295         return iterable;
296     }
297
298     // Iterate over the object
299     PyObject *iterator = PyObject_GetIter(sipPy);
300     PyObject *item;
301
302     // Maximum number of elements
303     int len = PyObject_Size(sipPy);
304     std::vector<int> *V = new std::vector<int>();
305     V->reserve(len);
306
307     if (len)
308     {
309         while ((item = PyIter_Next(iterator)))
310         {
311             if (!PyInt_Check(item))
312             {
313                 PyErr_Format(PyExc_TypeError, "object in iterable cannot be converted to float");
314                 *sipIsErr = 1;
315                 break;
316             }
317
318             int val = PyInt_AsLong(item);
319             V->push_back(val);
320
321             Py_DECREF(item);
322         }
323
324         Py_DECREF(iterator);
325
326         if (*sipIsErr)
327         {
328             delete V;
329             return 0;
330         }
331     }
332
333     *sipCppPtr = V;
334     return sipGetState(sipTransferObj);
335 %End
336 };
337
338
339 // ****************************************************
340 // Specialization for std::vector<unsigned int>
341 // ****************************************************
342
343 %MappedType std::vector<unsigned int>
344 {
345 %TypeHeaderCode
346 #include <vector>
347 %End
348
349 %ConvertFromTypeCode
350     PyObject *l;
351
352     // Create the Python list of the correct length.
353     if ((l = PyList_New(sipCpp -> size())) == NULL)
354         return NULL;
355
356     // Go through each element in the C++ instance and convert it to a
357     // wrapped object.
358     for (int i = 0; i < (int)sipCpp -> size(); ++i)
359     {
360         // Add the wrapper to the list.
361         PyList_SET_ITEM(l, i, PyInt_FromLong(sipCpp -> at(i)));
362     }
363
364     // Return the Python list.
365     return l;
366 %End
367
368 %ConvertToTypeCode
369     // Check if type is compatible
370     if (sipIsErr == NULL)
371     {
372         // Must be any iterable
373         PyObject *i = PyObject_GetIter(sipPy);
374         bool iterable = (i != NULL);
375         Py_XDECREF(i);
376         return iterable;
377     }
378
379     // Iterate over the object
380     PyObject *iterator = PyObject_GetIter(sipPy);
381     PyObject *item;
382
383     // Maximum number of elements
384     Py_ssize_t size = PyObject_Size(sipPy);
385     if (size == -1) {
386         Py_DECREF(iterator);
387         return 0;
388     }
389
390     unsigned int len = size;
391     std::vector<unsigned int> *V = new std::vector<unsigned int>();
392     V->reserve(len);
393
394     if (len)
395     {
396         while ((item = PyIter_Next(iterator)))
397         {
398             if (!PyInt_Check(item))
399             {
400                 PyErr_Format(PyExc_TypeError, "object in iterable cannot be converted to float");
401                 *sipIsErr = 1;
402                 break;
403             }
404
405             unsigned int val = PyInt_AsLong(item);
406             V->push_back(val);
407
408             Py_DECREF(item);
409         }
410
411         Py_DECREF(iterator);
412
413         if (*sipIsErr)
414         {
415             delete V;
416             return 0;
417         }
418     }
419
420     *sipCppPtr = V;
421     return sipGetState(sipTransferObj);
422 %End
423 };*/