2 * This file is part of the GROMACS molecular simulation package.
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.
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.
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.
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.
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.
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.
35 // SIP support for std::vector
36 // by Giovanni Bajo <rasky <at> develer.com>
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.
47 %MappedType std::vector<TYPE*>
54 PyObject *l = PyList_New(sipCpp -> size());
56 // Create the Python list of the correct length.
60 // Go through each element in the C++ instance and convert it to a
62 for (int i = 0; i < (int)sipCpp->size(); ++i) {
63 TYPE *cpp = sipCpp->at(i);
64 PyObject *pobj = sipConvertFromInstance(cpp, sipClass_TYPE, sipTransferObj);
66 // Get the Python wrapper for the Type instance, creating a new
67 // one if necessary, and handle any ownership transfer.
69 // There was an error so garbage collect the Python list.
74 // Add the wrapper to the list.
75 PyList_SET_ITEM(l, i, pobj);
78 // Return the Python list.
83 // Check if type is compatible
85 // Must be any iterable
86 PyObject *i = PyObject_GetIter(sipPy);
87 bool iterable = (i != NULL);
92 // Iterate over the object
93 PyObject *iterator = PyObject_GetIter(sipPy);
96 std::vector<TYPE*> *V = new std::vector<TYPE*>();
98 while ((item = PyIter_Next(iterator)))
100 if (!sipCanConvertToInstance(item, sipClass_TYPE, SIP_NOT_NONE)) {
101 PyErr_Format(PyExc_TypeError, "object in iterable cannot be converted to TYPE");
107 TYPE* p = reinterpret_cast<TYPE*>(
108 sipConvertToInstance(item, sipClass_TYPE, 0, SIP_NOT_NONE, &state, sipIsErr));
113 sipReleaseInstance(p, sipClass_TYPE, state);
125 return sipGetState(sipTransferObj);
129 // ****************************************************
130 // Specialization for std::vector<char*>
131 // ****************************************************
133 %MappedType std::vector<char*>
142 // Create the Python list of the correct length.
143 if ((l = PyList_New(sipCpp -> size())) == NULL)
146 // Go through each element in the C++ instance and convert it to a
148 for (int i = 0; i < (int)sipCpp -> size(); ++i)
150 // Add the wrapper to the list.
151 PyList_SET_ITEM(l, i, sipBuildResult(NULL, "A", sipCpp->at(i)));
154 // Return the Python list.
159 // Check if type is compatible
160 if (sipIsErr == NULL)
162 // Must be any iterable
163 PyObject *i = PyObject_GetIter(sipPy);
164 bool iterable = (i != NULL);
169 // Iterate over the object
170 PyObject *iterator = PyObject_GetIter(sipPy);
173 // Maximum number of elements
174 int len = PyObject_Size(sipPy);
175 std::vector<char*> *V = new std::vector<char*>();
180 while ((item = PyIter_Next(iterator)))
182 if (!PyUnicode_Check(item))
184 PyErr_Format(PyExc_TypeError, "object in iterable is not a string");
188 //FIXME: memory leak here
189 const char* str = strdup(sipString_AsLatin1String(&item));
191 V->push_back(const_cast<char*>(str));
206 return sipGetState(sipTransferObj);
211 // ****************************************************
212 // Specialization for std::vector<double>
213 // ****************************************************
215 %MappedType std::vector<double>
224 // Create the Python list of the correct length.
225 if ((l = PyList_New(sipCpp -> size())) == NULL)
228 // Go through each element in the C++ instance and convert it to a
230 for (int i = 0; i < (int)sipCpp -> size(); ++i)
232 // Add the wrapper to the list.
233 PyList_SET_ITEM(l, i, PyFloat_FromDouble(sipCpp -> at(i)));
236 // Return the Python list.
241 // Check if type is compatible
242 if (sipIsErr == NULL)
244 // Must be any iterable
245 PyObject *i = PyObject_GetIter(sipPy);
246 bool iterable = (i != NULL);
251 // Iterate over the object
252 PyObject *iterator = PyObject_GetIter(sipPy);
255 // Maximum number of elements
256 int len = PyObject_Size(sipPy);
257 std::vector<double> *V = new std::vector<double>();
262 while ((item = PyIter_Next(iterator)))
264 if (!PyNumber_Check(item))
266 PyErr_Format(PyExc_TypeError, "object in iterable is not a number");
271 PyObject *f = PyNumber_Float(item);
272 V->push_back(PyFloat_AsDouble(f));
288 return sipGetState(sipTransferObj);
292 // ****************************************************
293 // Specialization for std::vector<int>
294 // ****************************************************
296 %MappedType std::vector<int>
305 // Create the Python list of the correct length.
306 if ((l = PyList_New((SIP_SSIZE_T)sipCpp -> size())) == NULL)
309 // Go through each element in the C++ instance and convert it to a
311 for (int i = 0; i < (int)sipCpp -> size(); ++i)
313 // Add the wrapper to the list.
314 PyList_SET_ITEM(l, i, PyInt_FromLong(sipCpp -> at(i)));
317 // Return the Python list.
322 // Check if type is compatible
323 if (sipIsErr == NULL)
325 // Must be any iterable
326 PyObject *i = PyObject_GetIter(sipPy);
327 bool iterable = (i != NULL);
332 // Iterate over the object
333 PyObject *iterator = PyObject_GetIter(sipPy);
336 // Maximum number of elements
337 int len = PyObject_Size(sipPy);
338 std::vector<int> *V = new std::vector<int>();
343 while ((item = PyIter_Next(iterator)))
345 if (!PyInt_Check(item))
347 PyErr_Format(PyExc_TypeError, "object in iterable cannot be converted to float");
352 int val = PyInt_AsLong(item);
368 return sipGetState(sipTransferObj);
373 // ****************************************************
374 // Specialization for std::vector<unsigned int>
375 // ****************************************************
377 %MappedType std::vector<unsigned int>
386 // Create the Python list of the correct length.
387 if ((l = PyList_New(sipCpp -> size())) == NULL)
390 // Go through each element in the C++ instance and convert it to a
392 for (int i = 0; i < (int)sipCpp -> size(); ++i)
394 // Add the wrapper to the list.
395 PyList_SET_ITEM(l, i, PyInt_FromLong(sipCpp -> at(i)));
398 // Return the Python list.
403 // Check if type is compatible
404 if (sipIsErr == NULL)
406 // Must be any iterable
407 PyObject *i = PyObject_GetIter(sipPy);
408 bool iterable = (i != NULL);
413 // Iterate over the object
414 PyObject *iterator = PyObject_GetIter(sipPy);
417 // Maximum number of elements
418 Py_ssize_t size = PyObject_Size(sipPy);
424 unsigned int len = size;
425 std::vector<unsigned int> *V = new std::vector<unsigned int>();
430 while ((item = PyIter_Next(iterator)))
432 if (!PyInt_Check(item))
434 PyErr_Format(PyExc_TypeError, "object in iterable cannot be converted to float");
439 unsigned int val = PyInt_AsLong(item);
455 return sipGetState(sipTransferObj);