Update headers, fix style for some py files
[alexxy/gromacs.git] / src / python / sip / vector.sip
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2015, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 // SIP support for std::vector
36 // by Giovanni Bajo <rasky <at> develer.com>
37 // Public domain
38
39 // ****************************************************
40 // SIP generic implementation for std::vector<>
41 // ****************************************************
42 // ALas, this template-based generic implementation is valid only
43 // if the element type is a SIP-wrapped type. For basic types (int, double, etc.)
44 // we are forced to cut & paste to provide a specialization.
45
46 template<TYPE*>
47 %MappedType std::vector<TYPE*>
48 {
49 %TypeHeaderCode
50 #include <vector>
51 %End
52
53 %ConvertFromTypeCode
54     PyObject *l = PyList_New(sipCpp -> size());
55
56     // Create the Python list of the correct length.
57     if (!l)
58         return NULL;
59
60     // Go through each element in the C++ instance and convert it to a
61     // wrapped P2d.
62     for (int i = 0; i < (int)sipCpp->size(); ++i) {
63         TYPE *cpp = sipCpp->at(i);
64         PyObject *pobj = sipConvertFromInstance(cpp, sipClass_TYPE, sipTransferObj);
65
66         // Get the Python wrapper for the Type instance, creating a new
67         // one if necessary, and handle any ownership transfer.
68         if (!pobj) {
69             // There was an error so garbage collect the Python list.
70             Py_DECREF(l);
71             return NULL;
72         }
73
74         // Add the wrapper to the list.
75         PyList_SET_ITEM(l, i, pobj);
76     }
77
78     // Return the Python list.
79     return l;
80 %End
81
82 %ConvertToTypeCode
83     // Check if type is compatible
84     if (!sipIsErr) {
85         // Must be any iterable
86         PyObject *i = PyObject_GetIter(sipPy);
87         bool iterable = (i != NULL);
88         Py_XDECREF(i);
89         return iterable;
90     }
91
92     // Iterate over the object
93     PyObject *iterator = PyObject_GetIter(sipPy);
94     PyObject *item;
95
96     std::vector<TYPE*> *V = new std::vector<TYPE*>();
97
98     while ((item = PyIter_Next(iterator)))
99     {
100         if (!sipCanConvertToInstance(item, sipClass_TYPE, SIP_NOT_NONE)) {
101             PyErr_Format(PyExc_TypeError, "object in iterable cannot be converted to TYPE");
102             *sipIsErr = 1;
103             break;
104         }
105
106         int state;
107         TYPE* p = reinterpret_cast<TYPE*>(
108              sipConvertToInstance(item, sipClass_TYPE, 0, SIP_NOT_NONE, &state, sipIsErr));
109
110         if (!*sipIsErr)
111             V->push_back(p);
112
113         sipReleaseInstance(p, sipClass_TYPE, state);
114         Py_DECREF(item);
115     }
116
117     Py_DECREF(iterator);
118
119     if (*sipIsErr) {
120         delete V;
121         return 0;
122     }
123
124     *sipCppPtr = V;
125     return sipGetState(sipTransferObj);
126 %End
127 };
128
129 // ****************************************************
130 // Specialization for std::vector<char*>
131 // ****************************************************
132
133 %MappedType std::vector<char*>
134 {
135 %TypeHeaderCode
136 #include <vector>
137 %End
138
139 %ConvertFromTypeCode
140     PyObject *l;
141
142     // Create the Python list of the correct length.
143     if ((l = PyList_New(sipCpp -> size())) == NULL)
144         return NULL;
145
146     // Go through each element in the C++ instance and convert it to a
147     // wrapped object.
148     for (int i = 0; i < (int)sipCpp -> size(); ++i)
149     {
150         // Add the wrapper to the list.
151         PyList_SET_ITEM(l, i, sipBuildResult(NULL, "A", sipCpp->at(i)));
152     }
153
154     // Return the Python list.
155     return l;
156 %End
157
158 %ConvertToTypeCode
159     // Check if type is compatible
160     if (sipIsErr == NULL)
161     {
162         // Must be any iterable
163         PyObject *i = PyObject_GetIter(sipPy);
164         bool iterable = (i != NULL);
165         Py_XDECREF(i);
166         return iterable;
167     }
168
169     // Iterate over the object
170     PyObject *iterator = PyObject_GetIter(sipPy);
171     PyObject *item;
172
173     // Maximum number of elements
174     int len = PyObject_Size(sipPy);
175     std::vector<char*> *V = new std::vector<char*>();
176     V->reserve(len);
177
178     if (len)
179     {
180         while ((item = PyIter_Next(iterator)))
181         {
182             if (!PyUnicode_Check(item))
183             {
184                 PyErr_Format(PyExc_TypeError, "object in iterable is not a string");
185                 *sipIsErr = 1;
186                 break;
187             }
188             //FIXME: memory leak here
189             const char* str = strdup(sipString_AsLatin1String(&item));
190
191             V->push_back(const_cast<char*>(str));
192
193             Py_DECREF(item);
194         }
195
196         Py_DECREF(iterator);
197
198         if (*sipIsErr)
199         {
200             delete V;
201             return 0;
202         }
203     }
204
205     *sipCppPtr = V;
206     return sipGetState(sipTransferObj);
207 %End
208 };
209
210 /*
211 // ****************************************************
212 // Specialization for std::vector<double>
213 // ****************************************************
214
215 %MappedType std::vector<double>
216 {
217 %TypeHeaderCode
218 #include <vector>
219 %End
220
221 %ConvertFromTypeCode
222     PyObject *l;
223
224     // Create the Python list of the correct length.
225     if ((l = PyList_New(sipCpp -> size())) == NULL)
226         return NULL;
227
228     // Go through each element in the C++ instance and convert it to a
229     // wrapped object.
230     for (int i = 0; i < (int)sipCpp -> size(); ++i)
231     {
232         // Add the wrapper to the list.
233         PyList_SET_ITEM(l, i, PyFloat_FromDouble(sipCpp -> at(i)));
234     }
235
236     // Return the Python list.
237     return l;
238 %End
239
240 %ConvertToTypeCode
241     // Check if type is compatible
242     if (sipIsErr == NULL)
243     {
244         // Must be any iterable
245         PyObject *i = PyObject_GetIter(sipPy);
246         bool iterable = (i != NULL);
247         Py_XDECREF(i);
248         return iterable;
249     }
250
251     // Iterate over the object
252     PyObject *iterator = PyObject_GetIter(sipPy);
253     PyObject *item;
254
255     // Maximum number of elements
256     int len = PyObject_Size(sipPy);
257     std::vector<double> *V = new std::vector<double>();
258     V->reserve(len);
259
260     if (len)
261     {
262         while ((item = PyIter_Next(iterator)))
263         {
264             if (!PyNumber_Check(item))
265             {
266                 PyErr_Format(PyExc_TypeError, "object in iterable is not a number");
267                 *sipIsErr = 1;
268                 break;
269             }
270
271             PyObject *f = PyNumber_Float(item);
272             V->push_back(PyFloat_AsDouble(f));
273
274             Py_DECREF(f);
275             Py_DECREF(item);
276         }
277
278         Py_DECREF(iterator);
279
280         if (*sipIsErr)
281         {
282             delete V;
283             return 0;
284         }
285     }
286
287     *sipCppPtr = V;
288     return sipGetState(sipTransferObj);
289 %End
290 };
291
292 // ****************************************************
293 // Specialization for std::vector<int>
294 // ****************************************************
295
296 %MappedType std::vector<int>
297 {
298 %TypeHeaderCode
299 #include <vector>
300 %End
301
302 %ConvertFromTypeCode
303     PyObject *l;
304
305     // Create the Python list of the correct length.
306     if ((l = PyList_New((SIP_SSIZE_T)sipCpp -> size())) == NULL)
307         return NULL;
308
309     // Go through each element in the C++ instance and convert it to a
310     // wrapped object.
311     for (int i = 0; i < (int)sipCpp -> size(); ++i)
312     {
313         // Add the wrapper to the list.
314         PyList_SET_ITEM(l, i, PyInt_FromLong(sipCpp -> at(i)));
315     }
316
317     // Return the Python list.
318     return l;
319 %End
320
321 %ConvertToTypeCode
322     // Check if type is compatible
323     if (sipIsErr == NULL)
324     {
325         // Must be any iterable
326         PyObject *i = PyObject_GetIter(sipPy);
327         bool iterable = (i != NULL);
328         Py_XDECREF(i);
329         return iterable;
330     }
331
332     // Iterate over the object
333     PyObject *iterator = PyObject_GetIter(sipPy);
334     PyObject *item;
335
336     // Maximum number of elements
337     int len = PyObject_Size(sipPy);
338     std::vector<int> *V = new std::vector<int>();
339     V->reserve(len);
340
341     if (len)
342     {
343         while ((item = PyIter_Next(iterator)))
344         {
345             if (!PyInt_Check(item))
346             {
347                 PyErr_Format(PyExc_TypeError, "object in iterable cannot be converted to float");
348                 *sipIsErr = 1;
349                 break;
350             }
351
352             int val = PyInt_AsLong(item);
353             V->push_back(val);
354
355             Py_DECREF(item);
356         }
357
358         Py_DECREF(iterator);
359
360         if (*sipIsErr)
361         {
362             delete V;
363             return 0;
364         }
365     }
366
367     *sipCppPtr = V;
368     return sipGetState(sipTransferObj);
369 %End
370 };
371
372
373 // ****************************************************
374 // Specialization for std::vector<unsigned int>
375 // ****************************************************
376
377 %MappedType std::vector<unsigned int>
378 {
379 %TypeHeaderCode
380 #include <vector>
381 %End
382
383 %ConvertFromTypeCode
384     PyObject *l;
385
386     // Create the Python list of the correct length.
387     if ((l = PyList_New(sipCpp -> size())) == NULL)
388         return NULL;
389
390     // Go through each element in the C++ instance and convert it to a
391     // wrapped object.
392     for (int i = 0; i < (int)sipCpp -> size(); ++i)
393     {
394         // Add the wrapper to the list.
395         PyList_SET_ITEM(l, i, PyInt_FromLong(sipCpp -> at(i)));
396     }
397
398     // Return the Python list.
399     return l;
400 %End
401
402 %ConvertToTypeCode
403     // Check if type is compatible
404     if (sipIsErr == NULL)
405     {
406         // Must be any iterable
407         PyObject *i = PyObject_GetIter(sipPy);
408         bool iterable = (i != NULL);
409         Py_XDECREF(i);
410         return iterable;
411     }
412
413     // Iterate over the object
414     PyObject *iterator = PyObject_GetIter(sipPy);
415     PyObject *item;
416
417     // Maximum number of elements
418     Py_ssize_t size = PyObject_Size(sipPy);
419     if (size == -1) {
420         Py_DECREF(iterator);
421         return 0;
422     }
423
424     unsigned int len = size;
425     std::vector<unsigned int> *V = new std::vector<unsigned int>();
426     V->reserve(len);
427
428     if (len)
429     {
430         while ((item = PyIter_Next(iterator)))
431         {
432             if (!PyInt_Check(item))
433             {
434                 PyErr_Format(PyExc_TypeError, "object in iterable cannot be converted to float");
435                 *sipIsErr = 1;
436                 break;
437             }
438
439             unsigned int val = PyInt_AsLong(item);
440             V->push_back(val);
441
442             Py_DECREF(item);
443         }
444
445         Py_DECREF(iterator);
446
447         if (*sipIsErr)
448         {
449             delete V;
450             return 0;
451         }
452     }
453
454     *sipCppPtr = V;
455     return sipGetState(sipTransferObj);
456 %End
457 };*/