1// This is the SIP interface definition for the majority of the QList 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// Note that when we test the type of an object to see if it can be converted
23// to a collection we only check if it is iterable.  We do not check the
24// types of the contents - we assume we will be able to convert them when
25// requested.  This allows us to raise exceptions specific to an individual
26// object.  This approach doesn't work if there are overloads that can only be
27// distinguished by the types of the template arguments.  Currently there are
28// no such cases in PyQt5.  Note also that we don't consider strings to be
29// iterables.
30
31
32template<_TYPE_>
33%MappedType QList<_TYPE_>
34        /TypeHintIn="Iterable[_TYPE_]", TypeHintOut="List[_TYPE_]",
35        TypeHintValue="[]"/
36{
37%TypeHeaderCode
38#include <qlist.h>
39%End
40
41%ConvertFromTypeCode
42    PyObject *l = PyList_New(sipCpp->size());
43
44    if (!l)
45        return 0;
46
47    for (int i = 0; i < sipCpp->size(); ++i)
48    {
49        _TYPE_ *t = new _TYPE_(sipCpp->at(i));
50        PyObject *tobj = sipConvertFromNewType(t, sipType__TYPE_,
51                sipTransferObj);
52
53        if (!tobj)
54        {
55            delete t;
56            Py_DECREF(l);
57
58            return 0;
59        }
60
61        PyList_SetItem(l, i, tobj);
62    }
63
64    return l;
65%End
66
67%ConvertToTypeCode
68    PyObject *iter = PyObject_GetIter(sipPy);
69
70    if (!sipIsErr)
71    {
72        PyErr_Clear();
73        Py_XDECREF(iter);
74
75        return (iter
76#if PY_MAJOR_VERSION < 3
77                && !PyString_Check(sipPy)
78#endif
79                && !PyUnicode_Check(sipPy));
80    }
81
82    if (!iter)
83    {
84        *sipIsErr = 1;
85
86        return 0;
87    }
88
89    QList<_TYPE_> *ql = new QList<_TYPE_>;
90
91    for (Py_ssize_t i = 0; ; ++i)
92    {
93        PyErr_Clear();
94        PyObject *itm = PyIter_Next(iter);
95
96        if (!itm)
97        {
98            if (PyErr_Occurred())
99            {
100                delete ql;
101                Py_DECREF(iter);
102                *sipIsErr = 1;
103
104                return 0;
105            }
106
107            break;
108        }
109
110        int state;
111        _TYPE_ *t = reinterpret_cast<_TYPE_ *>(
112                sipForceConvertToType(itm, sipType__TYPE_, sipTransferObj,
113                        SIP_NOT_NONE, &state, sipIsErr));
114
115        if (*sipIsErr)
116        {
117            PyErr_Format(PyExc_TypeError,
118                    "index %zd has type '%s' but '_TYPE_' is expected", i,
119                    sipPyTypeName(Py_TYPE(itm)));
120
121            Py_DECREF(itm);
122            delete ql;
123            Py_DECREF(iter);
124
125            return 0;
126        }
127
128        ql->append(*t);
129
130        sipReleaseType(t, sipType__TYPE_, state);
131        Py_DECREF(itm);
132    }
133
134    Py_DECREF(iter);
135
136    *sipCppPtr = ql;
137
138    return sipGetState(sipTransferObj);
139%End
140};
141
142
143template<_TYPE_>
144%MappedType QList<_TYPE_ *>
145        /TypeHintIn="Iterable[_TYPE_]", TypeHintOut="List[_TYPE_]",
146        TypeHintValue="[]"/
147{
148%TypeHeaderCode
149#include <qlist.h>
150%End
151
152%ConvertFromTypeCode
153    int gc_enabled = sipEnableGC(0);
154    PyObject *l = PyList_New(sipCpp->size());
155
156    if (l)
157    {
158        for (int i = 0; i < sipCpp->size(); ++i)
159        {
160            _TYPE_ *t = sipCpp->at(i);
161
162            // The explicit (void *) cast allows _TYPE_ to be const.
163            PyObject *tobj = sipConvertFromType((void *)t, sipType__TYPE_,
164                    sipTransferObj);
165
166            if (!tobj)
167            {
168                Py_DECREF(l);
169                l = 0;
170
171                break;
172            }
173
174            PyList_SetItem(l, i, tobj);
175        }
176    }
177
178    sipEnableGC(gc_enabled);
179
180    return l;
181%End
182
183%ConvertToTypeCode
184    PyObject *iter = PyObject_GetIter(sipPy);
185
186    if (!sipIsErr)
187    {
188        PyErr_Clear();
189        Py_XDECREF(iter);
190
191        return (iter
192#if PY_MAJOR_VERSION < 3
193                && !PyString_Check(sipPy)
194#endif
195                && !PyUnicode_Check(sipPy));
196    }
197
198    if (!iter)
199    {
200        *sipIsErr = 1;
201
202        return 0;
203    }
204
205    QList<_TYPE_ *> *ql = new QList<_TYPE_ *>;
206
207    for (Py_ssize_t i = 0; ; ++i)
208    {
209        PyErr_Clear();
210        PyObject *itm = PyIter_Next(iter);
211
212        if (!itm)
213        {
214            if (PyErr_Occurred())
215            {
216                delete ql;
217                Py_DECREF(iter);
218                *sipIsErr = 1;
219
220                return 0;
221            }
222
223            break;
224        }
225
226        _TYPE_ *t = reinterpret_cast<_TYPE_ *>(
227                sipForceConvertToType(itm, sipType__TYPE_, sipTransferObj, 0,
228                        0, sipIsErr));
229
230        if (*sipIsErr)
231        {
232            PyErr_Format(PyExc_TypeError,
233                    "index %zd has type '%s' but '_TYPE_' is expected", i,
234                    sipPyTypeName(Py_TYPE(itm)));
235
236            Py_DECREF(itm);
237            delete ql;
238            Py_DECREF(iter);
239
240            return 0;
241        }
242
243        ql->append(t);
244
245        Py_DECREF(itm);
246    }
247
248    Py_DECREF(iter);
249
250    *sipCppPtr = ql;
251
252    return sipGetState(sipTransferObj);
253%End
254};
255
256
257template<_TYPE1_, _TYPE2_>
258%MappedType QList<QPair<_TYPE1_, _TYPE2_> >
259        /TypeHintIn="Iterable[Tuple[_TYPE1_, _TYPE2_]]",
260        TypeHintOut="List[Tuple[_TYPE1_, _TYPE2_]]", TypeHintValue="[]"/
261{
262%TypeHeaderCode
263#include <qlist.h>
264#include <qpair.h>
265%End
266
267%ConvertFromTypeCode
268    PyObject *l = PyList_New(sipCpp->size());
269
270    if (!l)
271        return 0;
272
273    for (int i = 0; i < sipCpp->size(); ++i)
274    {
275        const QPair<_TYPE1_, _TYPE2_> &p = sipCpp->at(i);
276        _TYPE1_ *s1 = new _TYPE1_(p.first);
277        _TYPE2_ *s2 = new _TYPE2_(p.second);
278        PyObject *pobj = sipBuildResult(NULL, "(NN)", s1, sipType__TYPE1_,
279                sipTransferObj, s2, sipType__TYPE2_, sipTransferObj);
280
281        if (!pobj)
282        {
283            delete s1;
284            delete s2;
285            Py_DECREF(l);
286
287            return 0;
288        }
289
290        PyList_SetItem(l, i, pobj);
291    }
292
293    return l;
294%End
295
296%ConvertToTypeCode
297    PyObject *iter = PyObject_GetIter(sipPy);
298
299    if (!sipIsErr)
300    {
301        PyErr_Clear();
302        Py_XDECREF(iter);
303
304        return (iter
305#if PY_MAJOR_VERSION < 3
306                && !PyString_Check(sipPy)
307#endif
308                && !PyUnicode_Check(sipPy));
309    }
310
311    if (!iter)
312    {
313        *sipIsErr = 1;
314
315        return 0;
316    }
317
318    QList<QPair<_TYPE1_, _TYPE2_> > *ql = new QList<QPair<_TYPE1_, _TYPE2_> >;
319
320    for (Py_ssize_t i = 0; ; ++i)
321    {
322        PyErr_Clear();
323        PyObject *seq = PyIter_Next(iter);
324
325        if (!seq)
326        {
327            if (PyErr_Occurred())
328            {
329                delete ql;
330                Py_DECREF(iter);
331                *sipIsErr = 1;
332
333                return 0;
334            }
335
336            break;
337        }
338
339        Py_ssize_t sub_len;
340
341        if (PySequence_Check(seq)
342#if PY_MAJOR_VERSION < 3
343                && !PyString_Check(seq)
344#endif
345                && !PyUnicode_Check(seq))
346            sub_len = PySequence_Size(seq);
347        else
348            sub_len = -1;
349
350        if (sub_len != 2)
351        {
352            if (sub_len < 0)
353                PyErr_Format(PyExc_TypeError,
354                        "index %zd has type '%s' but a 2 element non-string sequence is expected",
355                        i, sipPyTypeName(Py_TYPE(seq)));
356            else
357                PyErr_Format(PyExc_TypeError,
358                        "index %zd is a sequence of %zd sub-elements but 2 sub-elements are expected",
359                        i, sub_len);
360
361            Py_DECREF(seq);
362            delete ql;
363            Py_DECREF(iter);
364            *sipIsErr = 1;
365
366            return 0;
367        }
368
369        PyObject *itm1 = PySequence_GetItem(seq, 0);
370
371        if (!itm1)
372        {
373            Py_DECREF(seq);
374            delete ql;
375            Py_DECREF(iter);
376            *sipIsErr = 1;
377
378            return 0;
379        }
380
381        int state1;
382        _TYPE1_ *s1 = reinterpret_cast<_TYPE1_ *>(
383                sipForceConvertToType(itm1, sipType__TYPE1_, sipTransferObj,
384                        SIP_NOT_NONE, &state1, sipIsErr));
385
386        if (*sipIsErr)
387        {
388            PyErr_Format(PyExc_TypeError,
389                    "the first sub-element of index %zd has type '%s' but '_TYPE1_' is expected",
390                    i, sipPyTypeName(Py_TYPE(itm1)));
391
392            Py_DECREF(itm1);
393            Py_DECREF(seq);
394            delete ql;
395            Py_DECREF(iter);
396
397            return 0;
398        }
399
400        PyObject *itm2 = PySequence_GetItem(seq, 1);
401
402        if (!itm2)
403        {
404            sipReleaseType(s1, sipType__TYPE1_, state1);
405            Py_DECREF(itm1);
406            Py_DECREF(seq);
407            delete ql;
408            Py_DECREF(iter);
409            *sipIsErr = 1;
410
411            return 0;
412        }
413
414        int state2;
415        _TYPE2_ *s2 = reinterpret_cast<_TYPE2_ *>(
416                sipForceConvertToType(itm2, sipType__TYPE2_, sipTransferObj,
417                        SIP_NOT_NONE, &state2, sipIsErr));
418
419        if (*sipIsErr)
420        {
421            PyErr_Format(PyExc_TypeError,
422                    "the second sub-element of index %zd has type '%s' but '_TYPE2_' is expected",
423                    i, sipPyTypeName(Py_TYPE(itm2)));
424
425            Py_DECREF(itm2);
426            sipReleaseType(s1, sipType__TYPE1_, state1);
427            Py_DECREF(itm1);
428            Py_DECREF(seq);
429            delete ql;
430            Py_DECREF(iter);
431
432            return 0;
433        }
434
435        ql->append(QPair<_TYPE1_, _TYPE2_>(*s1, *s2));
436
437        sipReleaseType(s2, sipType__TYPE2_, state2);
438        Py_DECREF(itm2);
439        sipReleaseType(s1, sipType__TYPE1_, state1);
440        Py_DECREF(itm1);
441        Py_DECREF(seq);
442    }
443
444    Py_DECREF(iter);
445
446    *sipCppPtr = ql;
447
448    return sipGetState(sipTransferObj);
449%End
450};
451
452
453%If (Qt_5_1_0 -)
454
455%MappedType QList<QPair<int, int> >
456        /TypeHintIn="Iterable[Tuple[int, int]]",
457        TypeHintOut="List[Tuple[int, int]]", TypeHintValue="[]"/
458{
459%TypeHeaderCode
460#include <qlist.h>
461#include <qpair.h>
462%End
463
464%ConvertFromTypeCode
465    PyObject *l = PyList_New(sipCpp->size());
466
467    if (!l)
468        return 0;
469
470    for (int i = 0; i < sipCpp->size(); ++i)
471    {
472        const QPair<int, int> &p = sipCpp->at(i);
473        PyObject *pobj = Py_BuildValue((char *)"ii", p.first, p.second);
474
475        if (!pobj)
476        {
477            Py_DECREF(l);
478
479            return 0;
480        }
481
482        PyList_SetItem(l, i, pobj);
483    }
484
485    return l;
486%End
487
488%ConvertToTypeCode
489    PyObject *iter = PyObject_GetIter(sipPy);
490
491    if (!sipIsErr)
492    {
493        PyErr_Clear();
494        Py_XDECREF(iter);
495
496        return (iter
497#if PY_MAJOR_VERSION < 3
498                && !PyString_Check(sipPy)
499#endif
500                && !PyUnicode_Check(sipPy));
501    }
502
503    if (!iter)
504    {
505        *sipIsErr = 1;
506
507        return 0;
508    }
509
510    QList<QPair<int, int> > *ql = new QList<QPair<int, int> >;
511
512    for (Py_ssize_t i = 0; ; ++i)
513    {
514        PyErr_Clear();
515        PyObject *seq = PyIter_Next(iter);
516
517        if (!seq)
518        {
519            if (PyErr_Occurred())
520            {
521                delete ql;
522                Py_DECREF(iter);
523                *sipIsErr = 1;
524
525                return 0;
526            }
527
528            break;
529        }
530
531        Py_ssize_t sub_len;
532
533        if (PySequence_Check(seq)
534#if PY_MAJOR_VERSION < 3
535                && !PyString_Check(seq)
536#endif
537                && !PyUnicode_Check(seq))
538            sub_len = PySequence_Size(seq);
539        else
540            sub_len = -1;
541
542        if (sub_len != 2)
543        {
544            if (sub_len < 0)
545                PyErr_Format(PyExc_TypeError,
546                        "index %zd has type '%s' but a 2 element non-string sequence is expected",
547                        i, sipPyTypeName(Py_TYPE(seq)));
548            else
549                PyErr_Format(PyExc_TypeError,
550                        "index %zd is a sequence of %zd sub-elements but 2 sub-elements are expected",
551                        i, sub_len);
552
553            Py_DECREF(seq);
554            delete ql;
555            Py_DECREF(iter);
556            *sipIsErr = 1;
557
558            return 0;
559        }
560
561        PyObject *itm1 = PySequence_GetItem(seq, 0);
562
563        if (!itm1)
564        {
565            Py_DECREF(seq);
566            delete ql;
567            Py_DECREF(iter);
568            *sipIsErr = 1;
569
570            return 0;
571        }
572
573        int first = sipLong_AsInt(itm1);
574
575        if (PyErr_Occurred())
576        {
577            if (PyErr_ExceptionMatches(PyExc_TypeError))
578                PyErr_Format(PyExc_TypeError,
579                        "the first sub-element of index %zd has type '%s' but 'int' is expected",
580                        i, sipPyTypeName(Py_TYPE(itm1)));
581
582            Py_DECREF(itm1);
583            Py_DECREF(seq);
584            delete ql;
585            Py_DECREF(iter);
586            *sipIsErr = 1;
587
588            return 0;
589        }
590
591        PyObject *itm2 = PySequence_GetItem(seq, 1);
592
593        if (!itm2)
594        {
595            Py_DECREF(itm1);
596            Py_DECREF(seq);
597            delete ql;
598            Py_DECREF(iter);
599            *sipIsErr = 1;
600
601            return 0;
602        }
603
604        int second = sipLong_AsInt(itm2);
605
606        if (PyErr_Occurred())
607        {
608            if (PyErr_ExceptionMatches(PyExc_TypeError))
609                PyErr_Format(PyExc_TypeError,
610                        "the second sub-element of index %zd has type '%s' but 'int' is expected",
611                        i, sipPyTypeName(Py_TYPE(itm2)));
612
613            Py_DECREF(itm2);
614            Py_DECREF(itm1);
615            Py_DECREF(seq);
616            delete ql;
617            Py_DECREF(iter);
618            *sipIsErr = 1;
619
620            return 0;
621        }
622
623        ql->append(QPair<int, int>(first, second));
624
625        Py_DECREF(itm2);
626        Py_DECREF(itm1);
627        Py_DECREF(seq);
628    }
629
630    Py_DECREF(iter);
631
632    *sipCppPtr = ql;
633
634    return sipGetState(sipTransferObj);
635%End
636};
637
638%End
639
640
641%MappedType QList<int>
642        /TypeHintIn="Iterable[int]", TypeHintOut="List[int]",
643        TypeHintValue="[]"/
644{
645%TypeHeaderCode
646#include <qlist.h>
647%End
648
649%ConvertFromTypeCode
650    PyObject *l = PyList_New(sipCpp->size());
651
652    if (!l)
653        return 0;
654
655    for (int i = 0; i < sipCpp->size(); ++i)
656    {
657        PyObject *pobj = SIPLong_FromLong(sipCpp->value(i));
658
659        if (!pobj)
660        {
661            Py_DECREF(l);
662
663            return 0;
664        }
665
666        PyList_SetItem(l, i, pobj);
667    }
668
669    return l;
670%End
671
672%ConvertToTypeCode
673    PyObject *iter = PyObject_GetIter(sipPy);
674
675    if (!sipIsErr)
676    {
677        PyErr_Clear();
678        Py_XDECREF(iter);
679
680        return (iter
681#if PY_MAJOR_VERSION < 3
682                && !PyString_Check(sipPy)
683#endif
684                && !PyUnicode_Check(sipPy));
685    }
686
687    if (!iter)
688    {
689        *sipIsErr = 1;
690
691        return 0;
692    }
693
694    QList<int> *ql = new QList<int>;
695
696    for (Py_ssize_t i = 0; ; ++i)
697    {
698        PyErr_Clear();
699        PyObject *itm = PyIter_Next(iter);
700
701        if (!itm)
702        {
703            if (PyErr_Occurred())
704            {
705                delete ql;
706                Py_DECREF(iter);
707                *sipIsErr = 1;
708
709                return 0;
710            }
711
712            break;
713        }
714
715        int val = sipLong_AsInt(itm);
716
717        if (PyErr_Occurred())
718        {
719            if (PyErr_ExceptionMatches(PyExc_TypeError))
720                PyErr_Format(PyExc_TypeError,
721                        "index %zd has type '%s' but 'int' is expected", i,
722                        sipPyTypeName(Py_TYPE(itm)));
723
724            Py_DECREF(itm);
725            delete ql;
726            Py_DECREF(iter);
727            *sipIsErr = 1;
728
729            return 0;
730        }
731
732        ql->append(val);
733
734        Py_DECREF(itm);
735    }
736
737    Py_DECREF(iter);
738
739    *sipCppPtr = ql;
740
741    return sipGetState(sipTransferObj);
742%End
743};
744
745
746%MappedType QList<qreal>
747        /TypeHintIn="Iterable[float]", TypeHintOut="List[float]",
748        TypeHintValue="[]"/
749{
750%TypeHeaderCode
751#include <qlist.h>
752%End
753
754%ConvertFromTypeCode
755    PyObject *l = PyList_New(sipCpp->size());
756
757    if (!l)
758        return 0;
759
760    for (int i = 0; i < sipCpp->size(); ++i)
761    {
762        PyObject *pobj = PyFloat_FromDouble(sipCpp->value(i));
763
764        if (!pobj)
765        {
766            Py_DECREF(l);
767
768            return 0;
769        }
770
771        PyList_SetItem(l, i, pobj);
772    }
773
774    return l;
775%End
776
777%ConvertToTypeCode
778    PyObject *iter = PyObject_GetIter(sipPy);
779
780    if (!sipIsErr)
781    {
782        PyErr_Clear();
783        Py_XDECREF(iter);
784
785        return (iter
786#if PY_MAJOR_VERSION < 3
787                && !PyString_Check(sipPy)
788#endif
789                && !PyUnicode_Check(sipPy));
790    }
791
792    if (!iter)
793    {
794        *sipIsErr = 1;
795
796        return 0;
797    }
798
799    QList<qreal> *ql = new QList<qreal>;
800
801    for (Py_ssize_t i = 0; ; ++i)
802    {
803        PyErr_Clear();
804        PyObject *itm = PyIter_Next(iter);
805
806        if (!itm)
807        {
808            if (PyErr_Occurred())
809            {
810                delete ql;
811                Py_DECREF(iter);
812                *sipIsErr = 1;
813
814                return 0;
815            }
816
817            break;
818        }
819
820        PyErr_Clear();
821        double val = PyFloat_AsDouble(itm);
822
823        if (PyErr_Occurred())
824        {
825            PyErr_Format(PyExc_TypeError,
826                    "index %zd has type '%s' but 'float' is expected", i,
827                    sipPyTypeName(Py_TYPE(itm)));
828
829            Py_DECREF(itm);
830            delete ql;
831            Py_DECREF(iter);
832            *sipIsErr = 1;
833
834            return 0;
835        }
836
837        ql->append(val);
838
839        Py_DECREF(itm);
840    }
841
842    Py_DECREF(iter);
843
844    *sipCppPtr = ql;
845
846    return sipGetState(sipTransferObj);
847%End
848};
849
850
851%MappedType QList<Qt::DayOfWeek>
852        /TypeHintIn="Iterable[Qt.DayOfWeek]", TypeHintOut="List[Qt.DayOfWeek]",
853        TypeHintValue="[]"/
854{
855%TypeHeaderCode
856#include <Qt>
857%End
858
859%ConvertFromTypeCode
860    PyObject *l = PyList_New(sipCpp->size());
861
862    if (!l)
863        return 0;
864
865    for (int i = 0; i < sipCpp->size(); ++i)
866    {
867        PyObject *eobj = sipConvertFromEnum(sipCpp->at(i),
868                sipType_Qt_DayOfWeek);
869
870        if (!eobj)
871        {
872            Py_DECREF(l);
873
874            return 0;
875        }
876
877        PyList_SetItem(l, i, eobj);
878    }
879
880    return l;
881%End
882
883%ConvertToTypeCode
884    PyObject *iter = PyObject_GetIter(sipPy);
885
886    if (!sipIsErr)
887    {
888        PyErr_Clear();
889        Py_XDECREF(iter);
890
891        return (iter
892#if PY_MAJOR_VERSION < 3
893                && !PyString_Check(sipPy)
894#endif
895                && !PyUnicode_Check(sipPy));
896    }
897
898    if (!iter)
899    {
900        *sipIsErr = 1;
901
902        return 0;
903    }
904
905    QList<Qt::DayOfWeek> *ql = new QList<Qt::DayOfWeek>;
906
907    for (Py_ssize_t i = 0; ; ++i)
908    {
909        PyErr_Clear();
910        PyObject *itm = PyIter_Next(iter);
911
912        if (!itm)
913        {
914            if (PyErr_Occurred())
915            {
916                delete ql;
917                Py_DECREF(iter);
918                *sipIsErr = 1;
919
920                return 0;
921            }
922
923            break;
924        }
925
926        int v = sipConvertToEnum(itm, sipType_Qt_DayOfWeek);
927
928        if (PyErr_Occurred())
929        {
930            PyErr_Format(PyExc_TypeError,
931                    "index %zd has type '%s' but 'Qt.DayOfWeek' is expected",
932                    i, sipPyTypeName(Py_TYPE(itm)));
933
934            Py_DECREF(itm);
935            delete ql;
936            Py_DECREF(iter);
937            *sipIsErr = 1;
938
939            return 0;
940        }
941
942        ql->append(static_cast<Qt::DayOfWeek>(v));
943
944        Py_DECREF(itm);
945    }
946
947    Py_DECREF(iter);
948
949    *sipCppPtr = ql;
950
951    return sipGetState(sipTransferObj);
952%End
953};
954