1 /* -----------------------------------------------------------------------------
2  * std_list.i
3  *
4  * SWIG typemaps for std::list types
5  * ----------------------------------------------------------------------------- */
6 
7 %include <std_common.i>
8 %include <exception.i>
9 
10 // containers
11 
12 
13 // ------------------------------------------------------------------------
14 // std::list
15 //
16 // The aim of all that follows would be to integrate std::list with
17 // Perl as much as possible, namely, to allow the user to pass and
18 // be returned Perl arrays.
19 // const declarations are used to guess the intent of the function being
20 // exported; therefore, the following rationale is applied:
21 //
22 //   -- f(std::list<T>), f(const std::list<T>&), f(const std::list<T>*):
23 //      the parameter being read-only, either a Perl sequence or a
24 //      previously wrapped std::list<T> can be passed.
25 //   -- f(std::list<T>&), f(std::list<T>*):
26 //      the parameter must be modified; therefore, only a wrapped std::list
27 //      can be passed.
28 //   -- std::list<T> f():
29 //      the list is returned by copy; therefore, a Perl sequence of T:s
30 //      is returned which is most easily used in other Perl functions
31 //   -- std::list<T>& f(), std::list<T>* f(), const std::list<T>& f(),
32 //      const std::list<T>* f():
33 //      the list is returned by reference; therefore, a wrapped std::list
34 //      is returned
35 // ------------------------------------------------------------------------
36 
37 %{
38 #include <list>
39 %}
40 %fragment("<algorithm>");
41 %fragment("<stdexcept>");
42 
43 // exported class
44 
45 namespace std {
46 
47     template<class T> class list {
48         %typemap(in) list<T> (std::list<T>* v) {
49             if (SWIG_ConvertPtr($input,(void **) &v,
50                                 $&1_descriptor,1) != -1) {
51                 $1 = *v;
52             } else if (SvROK($input)) {
53                 AV *av = (AV *)SvRV($input);
54                 if (SvTYPE(av) != SVt_PVAV)
55                     SWIG_croak("Type error in argument $argnum of $symname. "
56                                "Expected an array of " #T);
57                 SV **tv;
58                 I32 len = av_len(av) + 1;
59                 T* obj;
60                 for (int i=0; i<len; i++) {
61                     tv = av_fetch(av, i, 0);
62                     if (SWIG_ConvertPtr(*tv, (void **)&obj,
63                                         $descriptor(T *),0) != -1) {
64                         $1.push_back(*obj);
65                     } else {
66                         SWIG_croak("Type error in argument $argnum of "
67                                    "$symname. "
68                                    "Expected an array of " #T);
69                     }
70                 }
71             } else {
72                 SWIG_croak("Type error in argument $argnum of $symname. "
73                            "Expected an array of " #T);
74             }
75         }
76         %typemap(in) const list<T>& (std::list<T> temp,
77                                        std::list<T>* v),
78                      const list<T>* (std::list<T> temp,
79                                        std::list<T>* v) {
80             if (SWIG_ConvertPtr($input,(void **) &v,
81                                 $1_descriptor,1) != -1) {
82                 $1 = v;
83             } else if (SvROK($input)) {
84                 AV *av = (AV *)SvRV($input);
85                 if (SvTYPE(av) != SVt_PVAV)
86                     SWIG_croak("Type error in argument $argnum of $symname. "
87                                "Expected an array of " #T);
88                 SV **tv;
89                 I32 len = av_len(av) + 1;
90                 T* obj;
91                 for (int i=0; i<len; i++) {
92                     tv = av_fetch(av, i, 0);
93                     if (SWIG_ConvertPtr(*tv, (void **)&obj,
94                                         $descriptor(T *),0) != -1) {
95                         temp.push_back(*obj);
96                     } else {
97                         SWIG_croak("Type error in argument $argnum of "
98                                    "$symname. "
99                                    "Expected an array of " #T);
100                     }
101                 }
102                 $1 = &temp;
103             } else {
104                 SWIG_croak("Type error in argument $argnum of $symname. "
105                            "Expected an array of " #T);
106             }
107         }
108         %typemap(out) list<T> {
109 	    std::list< T >::const_iterator i;
110             unsigned int j;
111             int len = $1.size();
112             SV **svs = new SV*[len];
113             for (i=$1.begin(), j=0; i!=$1.end(); i++, j++) {
114                 T* ptr = new T(*i);
115                 svs[j] = sv_newmortal();
116                 SWIG_MakePtr(svs[j], (void*) ptr,
117                              $descriptor(T *), $shadow|$owner);
118             }
119             AV *myav = av_make(len, svs);
120             delete[] svs;
121             $result = newRV_noinc((SV*) myav);
122             sv_2mortal($result);
123             argvi++;
124         }
125         %typecheck(SWIG_TYPECHECK_LIST) list<T> {
126             {
127                 /* wrapped list? */
128                 std::list< T >* v;
129                 if (SWIG_ConvertPtr($input,(void **) &v,
130                                     $1_&descriptor,0) != -1) {
131                     $1 = 1;
132                 } else if (SvROK($input)) {
133                     /* native sequence? */
134                     AV *av = (AV *)SvRV($input);
135                     if (SvTYPE(av) == SVt_PVAV) {
136                         SV **tv;
137                         I32 len = av_len(av) + 1;
138                         if (len == 0) {
139                             /* an empty sequence can be of any type */
140                             $1 = 1;
141                         } else {
142                             /* check the first element only */
143                             T* obj;
144                             tv = av_fetch(av, 0, 0);
145                             if (SWIG_ConvertPtr(*tv, (void **)&obj,
146                                                 $descriptor(T *),0) != -1)
147                                 $1 = 1;
148                             else
149                                 $1 = 0;
150                         }
151                     }
152                 } else {
153                     $1 = 0;
154                 }
155             }
156         }
157         %typecheck(SWIG_TYPECHECK_LIST) const list<T>&,
158                                           const list<T>* {
159             {
160                 /* wrapped list? */
161                 std::list< T >* v;
162                 if (SWIG_ConvertPtr($input,(void **) &v,
163                                     $1_descriptor,0) != -1) {
164                     $1 = 1;
165                 } else if (SvROK($input)) {
166                     /* native sequence? */
167                     AV *av = (AV *)SvRV($input);
168                     if (SvTYPE(av) == SVt_PVAV) {
169                         SV **tv;
170                         I32 len = av_len(av) + 1;
171                         if (len == 0) {
172                             /* an empty sequence can be of any type */
173                             $1 = 1;
174                         } else {
175                             /* check the first element only */
176                             T* obj;
177                             tv = av_fetch(av, 0, 0);
178                             if (SWIG_ConvertPtr(*tv, (void **)&obj,
179                                                 $descriptor(T *),0) != -1)
180                                 $1 = 1;
181                             else
182                                 $1 = 0;
183                         }
184                     }
185                 } else {
186                     $1 = 0;
187                 }
188             }
189         }
190       public:
191         typedef size_t size_type;
192         typedef ptrdiff_t difference_type;
193         typedef T value_type;
194         typedef value_type* pointer;
195         typedef const value_type* const_pointer;
196         typedef value_type& reference;
197         typedef const value_type& const_reference;
198 
199         list();
200         list(const list& other);
201 
202         unsigned int size() const;
203         bool empty() const;
204         void clear();
205         %rename(push) push_back;
206         void push_back(const T& x);
207     };
208 
209 
210     // specializations for built-ins
211 
212     %define specialize_std_list(T,CHECK_T,TO_T,FROM_T)
213     template<> class list<T> {
214         %typemap(in) list<T> (std::list<T>* v) {
215             if (SWIG_ConvertPtr($input,(void **) &v,
216                                 $&1_descriptor,1) != -1){
217                 $1 = *v;
218             } else if (SvROK($input)) {
219                 AV *av = (AV *)SvRV($input);
220                 if (SvTYPE(av) != SVt_PVAV)
221                     SWIG_croak("Type error in argument $argnum of $symname. "
222                                "Expected an array of " #T);
223                 SV **tv;
224                 I32 len = av_len(av) + 1;
225                 for (int i=0; i<len; i++) {
226                     tv = av_fetch(av, i, 0);
227                     if (CHECK_T(*tv)) {
228                         $1.push_back(TO_T(*tv));
229                     } else {
230                         SWIG_croak("Type error in argument $argnum of "
231                                    "$symname. "
232                                    "Expected an array of " #T);
233                     }
234                 }
235             } else {
236                 SWIG_croak("Type error in argument $argnum of $symname. "
237                            "Expected an array of " #T);
238             }
239         }
240         %typemap(in) const list<T>& (std::list<T> temp,
241                                        std::list<T>* v),
242                      const list<T>* (std::list<T> temp,
243                                        std::list<T>* v) {
244             if (SWIG_ConvertPtr($input,(void **) &v,
245                                 $1_descriptor,1) != -1) {
246                 $1 = v;
247             } else if (SvROK($input)) {
248                 AV *av = (AV *)SvRV($input);
249                 if (SvTYPE(av) != SVt_PVAV)
250                     SWIG_croak("Type error in argument $argnum of $symname. "
251                                "Expected an array of " #T);
252                 SV **tv;
253                 I32 len = av_len(av) + 1;
254                 T* obj;
255                 for (int i=0; i<len; i++) {
256                     tv = av_fetch(av, i, 0);
257                     if (CHECK_T(*tv)) {
258                         temp.push_back(TO_T(*tv));
259                     } else {
260                         SWIG_croak("Type error in argument $argnum of "
261                                    "$symname. "
262                                    "Expected an array of " #T);
263                     }
264                 }
265                 $1 = &temp;
266             } else {
267                 SWIG_croak("Type error in argument $argnum of $symname. "
268                            "Expected an array of " #T);
269             }
270         }
271         %typemap(out) list<T> {
272 	    std::list< T >::const_iterator i;
273             unsigned int j;
274             int len = $1.size();
275             SV **svs = new SV*[len];
276             for (i=$1.begin(), j=0; i!=$1.end(); i++, j++) {
277                 svs[j] = sv_newmortal();
278                 FROM_T(svs[j], *i);
279             }
280             AV *myav = av_make(len, svs);
281             delete[] svs;
282             $result = newRV_noinc((SV*) myav);
283             sv_2mortal($result);
284             argvi++;
285         }
286         %typecheck(SWIG_TYPECHECK_LIST) list<T> {
287             {
288                 /* wrapped list? */
289                 std::list< T >* v;
290                 if (SWIG_ConvertPtr($input,(void **) &v,
291                                     $1_&descriptor,0) != -1) {
292                     $1 = 1;
293                 } else if (SvROK($input)) {
294                     /* native sequence? */
295                     AV *av = (AV *)SvRV($input);
296                     if (SvTYPE(av) == SVt_PVAV) {
297                         SV **tv;
298                         I32 len = av_len(av) + 1;
299                         if (len == 0) {
300                             /* an empty sequence can be of any type */
301                             $1 = 1;
302                         } else {
303                             /* check the first element only */
304                             tv = av_fetch(av, 0, 0);
305                             if (CHECK_T(*tv))
306                                 $1 = 1;
307                             else
308                                 $1 = 0;
309                         }
310                     }
311                 } else {
312                     $1 = 0;
313                 }
314             }
315         }
316         %typecheck(SWIG_TYPECHECK_LIST) const list<T>&,
317                                           const list<T>* {
318             {
319                 /* wrapped list? */
320                 std::list< T >* v;
321                 if (SWIG_ConvertPtr($input,(void **) &v,
322                                     $1_descriptor,0) != -1) {
323                     $1 = 1;
324                 } else if (SvROK($input)) {
325                     /* native sequence? */
326                     AV *av = (AV *)SvRV($input);
327                     if (SvTYPE(av) == SVt_PVAV) {
328                         SV **tv;
329                         I32 len = av_len(av) + 1;
330                         if (len == 0) {
331                             /* an empty sequence can be of any type */
332                             $1 = 1;
333                         } else {
334                             /* check the first element only */
335                             tv = av_fetch(av, 0, 0);
336                             if (CHECK_T(*tv))
337                                 $1 = 1;
338                             else
339                                 $1 = 0;
340                         }
341                     }
342                 } else {
343                     $1 = 0;
344                 }
345             }
346         }
347       public:
348         typedef size_t size_type;
349         typedef T value_type;
350         typedef const value_type& const_reference;
351 
352         list();
353         list(const list& other);
354 
355         unsigned int size() const;
356         bool empty() const;
357         void clear();
358         %rename(push) push_back;
359         void push_back(T x);
360     };
361     %enddef
362 
363     specialize_std_list(bool,SvIOK,SvIVX,sv_setiv);
364     specialize_std_list(char,SvIOK,SvIVX,sv_setiv);
365     specialize_std_list(int,SvIOK,SvIVX,sv_setiv);
366     specialize_std_list(short,SvIOK,SvIVX,sv_setiv);
367     specialize_std_list(long,SvIOK,SvIVX,sv_setiv);
368     specialize_std_list(unsigned char,SvIOK,SvIVX,sv_setiv);
369     specialize_std_list(unsigned int,SvIOK,SvIVX,sv_setiv);
370     specialize_std_list(unsigned short,SvIOK,SvIVX,sv_setiv);
371     specialize_std_list(unsigned long,SvIOK,SvIVX,sv_setiv);
372     specialize_std_list(float,SvNIOK,SwigSvToNumber,sv_setnv);
373     specialize_std_list(double,SvNIOK,SwigSvToNumber,sv_setnv);
374     specialize_std_list(std::string,SvPOK,SvPVX,SwigSvFromString);
375 
376 }
377 
378