1// This is the SIP interface definition for the majority of the QSet 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 QSet<_TYPE_>
24        /TypeHintIn="Iterable[_TYPE_]", TypeHintOut="Set[_TYPE_]",
25        TypeHintValue="set()"/
26{
27%TypeHeaderCode
28#include <qset.h>
29%End
30
31%ConvertFromTypeCode
32    PyObject *s = PySet_New(0);
33
34    if (!s)
35        return 0;
36
37    QSet<_TYPE_>::const_iterator it = sipCpp->constBegin();
38    QSet<_TYPE_>::const_iterator end = sipCpp->constEnd();
39
40    while (it != end)
41    {
42        _TYPE_ *t = new _TYPE_(*it);
43        PyObject *tobj = sipConvertFromNewType(t, sipType__TYPE_,
44                sipTransferObj);
45
46        if (!tobj)
47        {
48            delete t;
49            Py_DECREF(s);
50
51            return 0;
52        }
53
54        PySet_Add(s, tobj);
55
56        ++it;
57    }
58
59    return s;
60%End
61
62%ConvertToTypeCode
63    PyObject *iter = PyObject_GetIter(sipPy);
64
65    if (!sipIsErr)
66    {
67        PyErr_Clear();
68        Py_XDECREF(iter);
69
70        return (iter
71#if PY_MAJOR_VERSION < 3
72                && !PyString_Check(sipPy)
73#endif
74                && !PyUnicode_Check(sipPy));
75    }
76
77    if (!iter)
78    {
79        *sipIsErr = 1;
80
81        return 0;
82    }
83
84    QSet<_TYPE_> *qs = new QSet<_TYPE_>;
85
86    for (Py_ssize_t i = 0; ; ++i)
87    {
88        PyErr_Clear();
89        PyObject *itm = PyIter_Next(iter);
90
91        if (!itm)
92        {
93            if (PyErr_Occurred())
94            {
95                delete qs;
96                Py_DECREF(iter);
97                *sipIsErr = 1;
98
99                return 0;
100            }
101
102            break;
103        }
104
105        int state;
106        _TYPE_ *t = reinterpret_cast<_TYPE_ *>(
107                sipForceConvertToType(itm, sipType__TYPE_, sipTransferObj,
108                        SIP_NOT_NONE, &state, sipIsErr));
109
110        if (*sipIsErr)
111        {
112            PyErr_Format(PyExc_TypeError,
113                    "index %zd has type '%s' but '_TYPE_' is expected", i,
114                    sipPyTypeName(Py_TYPE(itm)));
115
116            Py_DECREF(itm);
117            delete qs;
118            Py_DECREF(iter);
119
120            return 0;
121        }
122
123        qs->insert(*t);
124
125        sipReleaseType(t, sipType__TYPE_, state);
126        Py_DECREF(itm);
127    }
128
129    Py_DECREF(iter);
130
131    *sipCppPtr = qs;
132
133    return sipGetState(sipTransferObj);
134%End
135};
136
137
138template<_TYPE_>
139%MappedType QSet<_TYPE_ *>
140        /TypeHintIn="Iterable[_TYPE_]", TypeHintOut="Set[_TYPE_]",
141        TypeHintValue="set()"/
142{
143%TypeHeaderCode
144#include <qset.h>
145%End
146
147%ConvertFromTypeCode
148    int gc_enabled = sipEnableGC(0);
149    PyObject *s = PySet_New(0);
150
151    if (s)
152    {
153        QSet<_TYPE_ *>::const_iterator it = sipCpp->constBegin();
154        QSet<_TYPE_ *>::const_iterator end = sipCpp->constEnd();
155
156        while (it != end)
157        {
158            // The explicit (void *) cast allows _TYPE_ to be const.
159            PyObject *tobj = sipConvertFromType((void *)*it, sipType__TYPE_,
160                    sipTransferObj);
161
162            if (!tobj)
163            {
164                Py_DECREF(s);
165                s = 0;
166
167                break;
168            }
169
170            PySet_Add(s, tobj);
171
172            ++it;
173        }
174    }
175
176    sipEnableGC(gc_enabled);
177
178    return s;
179%End
180
181%ConvertToTypeCode
182    PyObject *iter = PyObject_GetIter(sipPy);
183
184    if (!sipIsErr)
185    {
186        PyErr_Clear();
187        Py_XDECREF(iter);
188
189        return (iter
190#if PY_MAJOR_VERSION < 3
191                && !PyString_Check(sipPy)
192#endif
193                && !PyUnicode_Check(sipPy));
194    }
195
196    if (!iter)
197    {
198        *sipIsErr = 1;
199
200        return 0;
201    }
202
203    QSet<_TYPE_ *> *qs = new QSet<_TYPE_ *>;
204
205    for (Py_ssize_t i = 0; ; ++i)
206    {
207        PyErr_Clear();
208        PyObject *itm = PyIter_Next(iter);
209
210        if (!itm)
211        {
212            if (PyErr_Occurred())
213            {
214                delete qs;
215                Py_DECREF(iter);
216                *sipIsErr = 1;
217
218                return 0;
219            }
220
221            break;
222        }
223
224        _TYPE_ *t = reinterpret_cast<_TYPE_ *>(
225                sipForceConvertToType(itm, sipType__TYPE_, sipTransferObj, 0,
226                        0, sipIsErr));
227
228        if (*sipIsErr)
229        {
230            PyErr_Format(PyExc_TypeError,
231                    "index %zd has type '%s' but '_TYPE_' is expected", i,
232                    sipPyTypeName(Py_TYPE(itm)));
233
234            Py_DECREF(itm);
235            delete qs;
236            Py_DECREF(iter);
237
238            return 0;
239        }
240
241        qs->insert(t);
242
243        Py_DECREF(itm);
244    }
245
246    Py_DECREF(iter);
247
248    *sipCppPtr = qs;
249
250    return sipGetState(sipTransferObj);
251%End
252};
253