1// This is the SIP interface definition for the majority of the QVector 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
22template<_TYPE_>
23%MappedType QVector<_TYPE_>
24        /TypeHintIn="Iterable[_TYPE_]", TypeHintOut="List[_TYPE_]",
25        TypeHintValue="[]"/
26{
27%TypeHeaderCode
28#include <qvector.h>
29%End
30
31%ConvertFromTypeCode
32    PyObject *l = PyList_New(sipCpp->size());
33
34    if (!l)
35        return 0;
36
37    for (int i = 0; i < sipCpp->size(); ++i)
38    {
39        _TYPE_ *t = new _TYPE_(sipCpp->at(i));
40        PyObject *tobj = sipConvertFromNewType(t, sipType__TYPE_,
41                sipTransferObj);
42
43        if (!tobj)
44        {
45            delete t;
46            Py_DECREF(l);
47
48            return 0;
49        }
50
51        PyList_SetItem(l, i, tobj);
52    }
53
54    return l;
55%End
56
57%ConvertToTypeCode
58    PyObject *iter = PyObject_GetIter(sipPy);
59
60    if (!sipIsErr)
61    {
62        PyErr_Clear();
63        Py_XDECREF(iter);
64
65        return (iter
66#if PY_MAJOR_VERSION < 3
67                && !PyString_Check(sipPy)
68#endif
69                && !PyUnicode_Check(sipPy));
70    }
71
72    if (!iter)
73    {
74        *sipIsErr = 1;
75
76        return 0;
77    }
78
79    QVector<_TYPE_> *qv = new QVector<_TYPE_>;
80
81    for (Py_ssize_t i = 0; ; ++i)
82    {
83        PyErr_Clear();
84        PyObject *itm = PyIter_Next(iter);
85
86        if (!itm)
87        {
88            if (PyErr_Occurred())
89            {
90                delete qv;
91                Py_DECREF(iter);
92                *sipIsErr = 1;
93
94                return 0;
95            }
96
97            break;
98        }
99
100        int state;
101        _TYPE_ *t = reinterpret_cast<_TYPE_ *>(
102                sipForceConvertToType(itm, sipType__TYPE_, sipTransferObj,
103                        SIP_NOT_NONE, &state, sipIsErr));
104
105        if (*sipIsErr)
106        {
107            PyErr_Format(PyExc_TypeError,
108                    "index %zd has type '%s' but '_TYPE_' is expected", i,
109                    sipPyTypeName(Py_TYPE(itm)));
110
111            Py_DECREF(itm);
112            delete qv;
113            Py_DECREF(iter);
114
115            return 0;
116        }
117
118        qv->append(*t);
119
120        sipReleaseType(t, sipType__TYPE_, state);
121        Py_DECREF(itm);
122    }
123
124    Py_DECREF(iter);
125
126    *sipCppPtr = qv;
127
128    return sipGetState(sipTransferObj);
129%End
130};
131
132
133template<_TYPE_>
134%MappedType QVector<_TYPE_ *>
135        /TypeHintIn="Iterable[_TYPE_]", TypeHintOut="List[_TYPE_]",
136        TypeHintValue="[]"/
137{
138%TypeHeaderCode
139#include <qvector.h>
140%End
141
142%ConvertFromTypeCode
143    int gc_enabled = sipEnableGC(0);
144    PyObject *l = PyList_New(sipCpp->size());
145
146    if (l)
147    {
148        for (int i = 0; i < sipCpp->size(); ++i)
149        {
150            _TYPE_ *t = sipCpp->at(i);
151
152            // The explicit (void *) cast allows _TYPE_ to be const.
153            PyObject *tobj = sipConvertFromNewType((void *)t, sipType__TYPE_,
154                    sipTransferObj);
155
156            if (!tobj)
157            {
158                Py_DECREF(l);
159                l = 0;
160
161                break;
162            }
163
164            PyList_SetItem(l, i, tobj);
165        }
166    }
167
168    sipEnableGC(gc_enabled);
169
170    return l;
171%End
172
173%ConvertToTypeCode
174    PyObject *iter = PyObject_GetIter(sipPy);
175
176    if (!sipIsErr)
177    {
178        PyErr_Clear();
179        Py_XDECREF(iter);
180
181        return (iter
182#if PY_MAJOR_VERSION < 3
183                && !PyString_Check(sipPy)
184#endif
185                && !PyUnicode_Check(sipPy));
186    }
187
188    if (!iter)
189    {
190        *sipIsErr = 1;
191
192        return 0;
193    }
194
195    QVector<_TYPE_ *> *qv = new QVector<_TYPE_ *>;
196
197    for (Py_ssize_t i = 0; ; ++i)
198    {
199        PyErr_Clear();
200        PyObject *itm = PyIter_Next(iter);
201
202        if (!itm)
203        {
204            if (PyErr_Occurred())
205            {
206                delete qv;
207                Py_DECREF(iter);
208                *sipIsErr = 1;
209
210                return 0;
211            }
212
213            break;
214        }
215
216        _TYPE_ *t = reinterpret_cast<_TYPE_ *>(
217                sipForceConvertToType(itm, sipType__TYPE_, sipTransferObj, 0,
218                        0, sipIsErr));
219
220        if (*sipIsErr)
221        {
222            PyErr_Format(PyExc_TypeError,
223                    "index %zd has type '%s' but '_TYPE_' is expected", i,
224                    sipPyTypeName(Py_TYPE(itm)));
225
226            Py_DECREF(itm);
227            delete qv;
228            Py_DECREF(iter);
229
230            return 0;
231        }
232
233        qv->append(t);
234
235        Py_DECREF(itm);
236    }
237
238    Py_DECREF(iter);
239
240    *sipCppPtr = qv;
241
242    return sipGetState(sipTransferObj);
243%End
244};
245
246
247template<qreal, _TYPE_>
248%MappedType QVector<QPair<qreal, _TYPE_> >
249        /TypeHintIn="Iterable[Tuple[float, _TYPE_]]",
250        TypeHintOut="List[Tuple[float, _TYPE_]]", TypeHintValue="[]"/
251{
252%TypeHeaderCode
253#include <qvector.h>
254#include <qpair.h>
255%End
256
257%ConvertFromTypeCode
258    PyObject *l = PyList_New(sipCpp->size());
259
260    if (!l)
261        return 0;
262
263    for (int i = 0; i < sipCpp->size(); ++i)
264    {
265        const QPair<qreal, _TYPE_> &p = sipCpp->at(i);
266        _TYPE_ *s2 = new _TYPE_(p.second);
267        PyObject *pobj = sipBuildResult(NULL, "(dN)", (double)p.first, s2,
268                sipType__TYPE_, sipTransferObj);
269
270        if (!pobj)
271        {
272            delete s2;
273            Py_DECREF(l);
274
275            return 0;
276        }
277
278        PyList_SetItem(l, i, pobj);
279    }
280
281    return l;
282%End
283
284%ConvertToTypeCode
285    PyObject *iter = PyObject_GetIter(sipPy);
286
287    if (!sipIsErr)
288    {
289        PyErr_Clear();
290        Py_XDECREF(iter);
291
292        return (iter
293#if PY_MAJOR_VERSION < 3
294                && !PyString_Check(sipPy)
295#endif
296                && !PyUnicode_Check(sipPy));
297    }
298
299    if (!iter)
300    {
301        *sipIsErr = 1;
302
303        return 0;
304    }
305
306    QVector<QPair<qreal, _TYPE_> > *qv = new QVector<QPair<qreal, _TYPE_> >;
307
308    for (Py_ssize_t i = 0; ; ++i)
309    {
310        PyErr_Clear();
311        PyObject *seq = PyIter_Next(iter);
312
313        if (!seq)
314        {
315            if (PyErr_Occurred())
316            {
317                delete qv;
318                Py_DECREF(iter);
319                *sipIsErr = 1;
320
321                return 0;
322            }
323
324            break;
325        }
326
327        Py_ssize_t sub_len;
328
329        if (PySequence_Check(seq)
330#if PY_MAJOR_VERSION < 3
331                && !PyString_Check(seq)
332#endif
333                && !PyUnicode_Check(seq))
334            sub_len = PySequence_Size(seq);
335        else
336            sub_len = -1;
337
338        if (sub_len != 2)
339        {
340            if (sub_len < 0)
341                PyErr_Format(PyExc_TypeError,
342                        "index %zd has type '%s' but a 2 element non-string sequence is expected",
343                        i, sipPyTypeName(Py_TYPE(seq)));
344            else
345                PyErr_Format(PyExc_TypeError,
346                        "index %zd is a sequence of %zd sub-elements but 2 sub-elements are expected",
347                        i, sub_len);
348
349            Py_DECREF(seq);
350            delete qv;
351            Py_DECREF(iter);
352            *sipIsErr = 1;
353
354            return 0;
355        }
356
357        PyObject *itm1 = PySequence_GetItem(seq, 0);
358
359        if (!itm1)
360        {
361            Py_DECREF(seq);
362            delete qv;
363            Py_DECREF(iter);
364            *sipIsErr = 1;
365
366            return 0;
367        }
368
369        PyErr_Clear();
370        qreal s1 = PyFloat_AsDouble(itm1);
371
372        if (PyErr_Occurred())
373        {
374            PyErr_Format(PyExc_TypeError,
375                    "the first sub-element of index %zd has type '%s' but 'float' is expected",
376                    i, sipPyTypeName(Py_TYPE(itm1)));
377
378            Py_DECREF(itm1);
379            Py_DECREF(seq);
380            delete qv;
381            Py_DECREF(iter);
382            *sipIsErr = 1;
383
384            return 0;
385        }
386
387        PyObject *itm2 = PySequence_GetItem(seq, 1);
388
389        if (!itm2)
390        {
391            Py_DECREF(itm1);
392            Py_DECREF(seq);
393            delete qv;
394            Py_DECREF(iter);
395            *sipIsErr = 1;
396
397            return 0;
398        }
399
400        int state2;
401        _TYPE_ *s2 = reinterpret_cast<_TYPE_ *>(
402                sipForceConvertToType(itm2, sipType__TYPE_, sipTransferObj,
403                        SIP_NOT_NONE, &state2, sipIsErr));
404
405        if (*sipIsErr)
406        {
407            PyErr_Format(PyExc_TypeError,
408                    "the second sub-element of index %zd has type '%s' but '_TYPE_' is expected",
409                    i, sipPyTypeName(Py_TYPE(itm2)));
410
411            Py_DECREF(itm2);
412            Py_DECREF(itm1);
413            Py_DECREF(seq);
414            delete qv;
415            Py_DECREF(iter);
416
417            return 0;
418        }
419
420        qv->append(QPair<qreal, _TYPE_>(s1, *s2));
421
422        sipReleaseType(s2, sipType__TYPE_, state2);
423        Py_DECREF(itm2);
424        Py_DECREF(itm1);
425        Py_DECREF(seq);
426    }
427
428    Py_DECREF(iter);
429
430    *sipCppPtr = qv;
431
432    return sipGetState(sipTransferObj);
433%End
434};
435
436
437%MappedType QVector<int>
438        /TypeHintIn="Iterable[int]", TypeHintOut="List[int]",
439        TypeHintValue="[]"/
440{
441%TypeHeaderCode
442#include <qvector.h>
443%End
444
445%ConvertFromTypeCode
446    PyObject *l = PyList_New(sipCpp->size());
447
448    if (!l)
449        return 0;
450
451    for (int i = 0; i < sipCpp->size(); ++i)
452    {
453        PyObject *pobj = SIPLong_FromLong(sipCpp->value(i));
454
455        if (!pobj)
456        {
457            Py_DECREF(l);
458
459            return 0;
460        }
461
462        PyList_SetItem(l, i, pobj);
463    }
464
465    return l;
466%End
467
468%ConvertToTypeCode
469    PyObject *iter = PyObject_GetIter(sipPy);
470
471    if (!sipIsErr)
472    {
473        PyErr_Clear();
474        Py_XDECREF(iter);
475
476        return (iter
477#if PY_MAJOR_VERSION < 3
478                && !PyString_Check(sipPy)
479#endif
480                && !PyUnicode_Check(sipPy));
481    }
482
483    if (!iter)
484    {
485        *sipIsErr = 1;
486
487        return 0;
488    }
489
490    QVector<int> *qv = new QVector<int>;
491
492    for (Py_ssize_t i = 0; ; ++i)
493    {
494        PyErr_Clear();
495        PyObject *itm = PyIter_Next(iter);
496
497        if (!itm)
498        {
499            if (PyErr_Occurred())
500            {
501                delete qv;
502                Py_DECREF(iter);
503                *sipIsErr = 1;
504
505                return 0;
506            }
507
508            break;
509        }
510
511        int val = sipLong_AsInt(itm);
512
513        if (PyErr_Occurred())
514        {
515            if (PyErr_ExceptionMatches(PyExc_TypeError))
516                PyErr_Format(PyExc_TypeError,
517                        "index %zd has type '%s' but 'int' is expected", i,
518                        sipPyTypeName(Py_TYPE(itm)));
519
520            Py_DECREF(itm);
521            delete qv;
522            Py_DECREF(iter);
523            *sipIsErr = 1;
524
525            return 0;
526        }
527
528        qv->append(val);
529
530        Py_DECREF(itm);
531    }
532
533    Py_DECREF(iter);
534
535    *sipCppPtr = qv;
536
537    return sipGetState(sipTransferObj);
538%End
539};
540
541
542%If (Qt_5_12_0 -)
543
544%MappedType QVector<quint16>
545        /TypeHintIn="Iterable[int]", TypeHintOut="List[int]",
546        TypeHintValue="[]"/
547{
548%TypeHeaderCode
549#include <qvector.h>
550%End
551
552%ConvertFromTypeCode
553    PyObject *l = PyList_New(sipCpp->size());
554
555    if (!l)
556        return 0;
557
558    for (int i = 0; i < sipCpp->size(); ++i)
559    {
560        PyObject *pobj = SIPLong_FromLong(sipCpp->value(i));
561
562        if (!pobj)
563        {
564            Py_DECREF(l);
565
566            return 0;
567        }
568
569        PyList_SetItem(l, i, pobj);
570    }
571
572    return l;
573%End
574
575%ConvertToTypeCode
576    PyObject *iter = PyObject_GetIter(sipPy);
577
578    if (!sipIsErr)
579    {
580        PyErr_Clear();
581        Py_XDECREF(iter);
582
583        return (iter
584#if PY_MAJOR_VERSION < 3
585                && !PyString_Check(sipPy)
586#endif
587                && !PyUnicode_Check(sipPy));
588    }
589
590    if (!iter)
591    {
592        *sipIsErr = 1;
593
594        return 0;
595    }
596
597    QVector<quint16> *qv = new QVector<quint16>;
598
599    for (Py_ssize_t i = 0; ; ++i)
600    {
601        PyErr_Clear();
602        PyObject *itm = PyIter_Next(iter);
603
604        if (!itm)
605        {
606            if (PyErr_Occurred())
607            {
608                delete qv;
609                Py_DECREF(iter);
610                *sipIsErr = 1;
611
612                return 0;
613            }
614
615            break;
616        }
617
618        quint16 val = sipLong_AsUnsignedShort(itm);
619
620        if (PyErr_Occurred())
621        {
622            if (PyErr_ExceptionMatches(PyExc_TypeError))
623                PyErr_Format(PyExc_TypeError,
624                        "index %zd has type '%s' but 'int' is expected", i,
625                        sipPyTypeName(Py_TYPE(itm)));
626
627            Py_DECREF(itm);
628            delete qv;
629            Py_DECREF(iter);
630            *sipIsErr = 1;
631
632            return 0;
633        }
634
635        qv->append(val);
636
637        Py_DECREF(itm);
638    }
639
640    Py_DECREF(iter);
641
642    *sipCppPtr = qv;
643
644    return sipGetState(sipTransferObj);
645%End
646};
647
648%End
649