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