1// This is the SIP interface definition for the majority of the QPair based
2// mapped types.
3//
4// Copyright (c) 2021 Riverbank Computing Limited <info@riverbankcomputing.com>
5//
6// This file is part of PyQt5.
7//
8// This file may be used under the terms of the GNU General Public License
9// version 3.0 as published by the Free Software Foundation and appearing in
10// the file LICENSE included in the packaging of this file.  Please review the
11// following information to ensure the GNU General Public License version 3.0
12// requirements will be met: http://www.gnu.org/copyleft/gpl.html.
13//
14// If you do not wish to use this file under the terms of the GPL version 3.0
15// then you may purchase a commercial license.  For more information contact
16// info@riverbankcomputing.com.
17//
18// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
19// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20
21
22%If (Qt_5_10_0 -)
23
24template<_TYPE1_, _TYPE2_>
25%MappedType QPair<_TYPE1_, _TYPE2_> /TypeHint="Tuple[_TYPE1_, _TYPE2_]"/
26{
27%TypeHeaderCode
28#include <qpair.h>
29%End
30
31%ConvertFromTypeCode
32    _TYPE1_ *first = new _TYPE1_(sipCpp->first);
33    _TYPE2_ *second = new _TYPE2_(sipCpp->second);
34    PyObject *t = sipBuildResult(NULL, "(NN)", first, sipType__TYPE1_,
35            sipTransferObj, second, sipType__TYPE2_, sipTransferObj);
36
37    if (!t)
38    {
39        delete first;
40        delete second;
41
42        return 0;
43    }
44
45    return t;
46%End
47
48%ConvertToTypeCode
49    if (!sipIsErr)
50        return (PySequence_Check(sipPy)
51#if PY_MAJOR_VERSION < 3
52                && !PyString_Check(sipPy)
53#endif
54                && !PyUnicode_Check(sipPy));
55
56    Py_ssize_t len = PySequence_Size(sipPy);
57
58    if (len != 2)
59    {
60        // A negative length should only be an internal error so let the
61        // original exception stand.
62        if (len >= 0)
63            PyErr_Format(PyExc_TypeError,
64                    "sequence has %zd elements but 2 elements are expected",
65                    len);
66
67        *sipIsErr = 1;
68
69        return 0;
70    }
71
72    PyObject *firstobj = PySequence_GetItem(sipPy, 0);
73
74    if (!firstobj)
75    {
76        *sipIsErr = 1;
77
78        return 0;
79    }
80
81    int firststate;
82    _TYPE1_ *first = reinterpret_cast<_TYPE1_ *>(
83            sipForceConvertToType(firstobj, sipType__TYPE1_, sipTransferObj,
84                    SIP_NOT_NONE, &firststate, sipIsErr));
85
86    if (*sipIsErr)
87    {
88        PyErr_Format(PyExc_TypeError,
89                "the first element has type '%s' but '_TYPE1_' is expected",
90                sipPyTypeName(Py_TYPE(firstobj)));
91
92        return 0;
93    }
94
95    PyObject *secondobj = PySequence_GetItem(sipPy, 1);
96
97    if (!secondobj)
98    {
99        sipReleaseType(first, sipType__TYPE1_, firststate);
100        Py_DECREF(firstobj);
101        *sipIsErr = 1;
102
103        return 0;
104    }
105
106    int secondstate;
107    _TYPE2_ *second = reinterpret_cast<_TYPE2_ *>(
108            sipForceConvertToType(secondobj, sipType__TYPE2_, sipTransferObj,
109                    SIP_NOT_NONE, &secondstate, sipIsErr));
110
111    if (*sipIsErr)
112    {
113        PyErr_Format(PyExc_TypeError,
114                "the second element has type '%s' but '_TYPE2_' is expected",
115                sipPyTypeName(Py_TYPE(secondobj)));
116
117        Py_DECREF(secondobj);
118        sipReleaseType(first, sipType__TYPE1_, firststate);
119        Py_DECREF(firstobj);
120        *sipIsErr = 1;
121
122        return 0;
123    }
124
125    *sipCppPtr = new QPair<_TYPE1_, _TYPE2_>(*first, *second);
126
127    sipReleaseType(second, sipType__TYPE2_, secondstate);
128    Py_DECREF(secondobj);
129    sipReleaseType(first, sipType__TYPE1_, firststate);
130    Py_DECREF(firstobj);
131
132    return sipGetState(sipTransferObj);
133%End
134};
135
136%End
137
138
139template<_TYPE_>
140%MappedType QPair<_TYPE_, int> /TypeHint="Tuple[_TYPE_, int]"/
141{
142%TypeHeaderCode
143#include <qpair.h>
144%End
145
146%ConvertFromTypeCode
147    _TYPE_ *first = new _TYPE_(sipCpp->first);
148    PyObject *t = sipBuildResult(NULL, "(Ni)", first, sipType__TYPE_,
149            sipTransferObj, sipCpp->second);
150
151    if (!t)
152    {
153        delete first;
154
155        return 0;
156    }
157
158    return t;
159%End
160
161%ConvertToTypeCode
162    if (!sipIsErr)
163        return (PySequence_Check(sipPy)
164#if PY_MAJOR_VERSION < 3
165                && !PyString_Check(sipPy)
166#endif
167                && !PyUnicode_Check(sipPy));
168
169    Py_ssize_t len = PySequence_Size(sipPy);
170
171    if (len != 2)
172    {
173        // A negative length should only be an internal error so let the
174        // original exception stand.
175        if (len >= 0)
176            PyErr_Format(PyExc_TypeError,
177                    "sequence has %zd elements but 2 elements are expected",
178                    len);
179
180        *sipIsErr = 1;
181
182        return 0;
183    }
184
185    PyObject *firstobj = PySequence_GetItem(sipPy, 0);
186
187    if (!firstobj)
188    {
189        *sipIsErr = 1;
190
191        return 0;
192    }
193
194    int firststate;
195    _TYPE_ *first = reinterpret_cast<_TYPE_ *>(
196            sipForceConvertToType(firstobj, sipType__TYPE_, sipTransferObj,
197                    SIP_NOT_NONE, &firststate, sipIsErr));
198
199    if (*sipIsErr)
200    {
201        PyErr_Format(PyExc_TypeError,
202                "the first element has type '%s' but '_TYPE_' is expected",
203                sipPyTypeName(Py_TYPE(firstobj)));
204
205        return 0;
206    }
207
208    PyObject *secondobj = PySequence_GetItem(sipPy, 1);
209
210    if (!secondobj)
211    {
212        sipReleaseType(first, sipType__TYPE_, firststate);
213        Py_DECREF(firstobj);
214        *sipIsErr = 1;
215
216        return 0;
217    }
218
219    int second = sipLong_AsInt(secondobj);
220
221    if (PyErr_Occurred())
222    {
223        if (PyErr_ExceptionMatches(PyExc_TypeError))
224            PyErr_Format(PyExc_TypeError,
225                    "the second element has type '%s' but 'int' is expected",
226                    sipPyTypeName(Py_TYPE(secondobj)));
227
228        Py_DECREF(secondobj);
229        sipReleaseType(first, sipType__TYPE_, firststate);
230        Py_DECREF(firstobj);
231        *sipIsErr = 1;
232
233        return 0;
234    }
235
236    *sipCppPtr = new QPair<_TYPE_, int>(*first, second);
237
238    Py_DECREF(secondobj);
239    sipReleaseType(first, sipType__TYPE_, firststate);
240    Py_DECREF(firstobj);
241
242    return sipGetState(sipTransferObj);
243%End
244};
245
246
247%MappedType QPair<int, int> /TypeHint="Tuple[int, int]"/
248{
249%TypeHeaderCode
250#include <qpair.h>
251%End
252
253%ConvertFromTypeCode
254    return Py_BuildValue("(ii)", sipCpp->first, sipCpp->second);
255%End
256
257%ConvertToTypeCode
258    if (!sipIsErr)
259        return (PySequence_Check(sipPy)
260#if PY_MAJOR_VERSION < 3
261                && !PyString_Check(sipPy)
262#endif
263                && !PyUnicode_Check(sipPy));
264
265    Py_ssize_t len = PySequence_Size(sipPy);
266
267    if (len != 2)
268    {
269        // A negative length should only be an internal error so let the
270        // original exception stand.
271        if (len >= 0)
272            PyErr_Format(PyExc_TypeError,
273                    "sequence has %zd elements but 2 elements are expected",
274                    len);
275
276        *sipIsErr = 1;
277
278        return 0;
279    }
280
281    PyObject *firstobj = PySequence_GetItem(sipPy, 0);
282
283    if (!firstobj)
284    {
285        *sipIsErr = 1;
286
287        return 0;
288    }
289
290    int first = sipLong_AsInt(firstobj);
291
292    if (PyErr_Occurred())
293    {
294        if (PyErr_ExceptionMatches(PyExc_TypeError))
295            PyErr_Format(PyExc_TypeError,
296                    "the first element has type '%s' but 'int' is expected",
297                    sipPyTypeName(Py_TYPE(firstobj)));
298
299        *sipIsErr = 1;
300
301        return 0;
302    }
303
304    PyObject *secondobj = PySequence_GetItem(sipPy, 1);
305
306    if (!secondobj)
307    {
308        Py_DECREF(firstobj);
309        *sipIsErr = 1;
310
311        return 0;
312    }
313
314    int second = sipLong_AsInt(secondobj);
315
316    if (PyErr_Occurred())
317    {
318        if (PyErr_ExceptionMatches(PyExc_TypeError))
319            PyErr_Format(PyExc_TypeError,
320                    "the second element has type '%s' but 'int' is expected",
321                    sipPyTypeName(Py_TYPE(secondobj)));
322
323        Py_DECREF(secondobj);
324        Py_DECREF(firstobj);
325        *sipIsErr = 1;
326
327        return 0;
328    }
329
330    *sipCppPtr = new QPair<int, int>(first, second);
331
332    Py_DECREF(secondobj);
333    Py_DECREF(firstobj);
334
335    return sipGetState(sipTransferObj);
336%End
337};
338