import source from 1.3.40
[external/swig.git] / Lib / perl5 / std_vector.i
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_vector.i
6  *
7  * SWIG typemaps for std::vector types
8  * ----------------------------------------------------------------------------- */
9
10 %include <std_common.i>
11
12 // ------------------------------------------------------------------------
13 // std::vector
14 // 
15 // The aim of all that follows would be to integrate std::vector with 
16 // Perl as much as possible, namely, to allow the user to pass and 
17 // be returned Perl arrays.
18 // const declarations are used to guess the intent of the function being
19 // exported; therefore, the following rationale is applied:
20 // 
21 //   -- f(std::vector<T>), f(const std::vector<T>&), f(const std::vector<T>*):
22 //      the parameter being read-only, either a Perl sequence or a
23 //      previously wrapped std::vector<T> can be passed.
24 //   -- f(std::vector<T>&), f(std::vector<T>*):
25 //      the parameter must be modified; therefore, only a wrapped std::vector
26 //      can be passed.
27 //   -- std::vector<T> f():
28 //      the vector is returned by copy; therefore, a Perl sequence of T:s 
29 //      is returned which is most easily used in other Perl functions
30 //   -- std::vector<T>& f(), std::vector<T>* f(), const std::vector<T>& f(),
31 //      const std::vector<T>* f():
32 //      the vector is returned by reference; therefore, a wrapped std::vector
33 //      is returned
34 // ------------------------------------------------------------------------
35
36 %{
37 #include <vector>
38 #include <algorithm>
39 #include <stdexcept>
40 %}
41
42 // exported class
43
44 namespace std {
45     
46     template<class T> class vector {
47         %typemap(in) vector<T> (std::vector<T>* v) {
48             if (SWIG_ConvertPtr($input,(void **) &v, 
49                                 $&1_descriptor,1) != -1) {
50                 $1 = *v;
51             } else if (SvROK($input)) {
52                 AV *av = (AV *)SvRV($input);
53                 if (SvTYPE(av) != SVt_PVAV)
54                     SWIG_croak("Type error in argument $argnum of $symname. "
55                                "Expected an array of " #T);
56                 SV **tv;
57                 I32 len = av_len(av) + 1;
58                 T* obj;
59                 for (int i=0; i<len; i++) {
60                     tv = av_fetch(av, i, 0);
61                     if (SWIG_ConvertPtr(*tv, (void **)&obj, 
62                                         $descriptor(T *),0) != -1) {
63                         $1.push_back(*obj);
64                     } else {
65                         SWIG_croak("Type error in argument $argnum of "
66                                    "$symname. "
67                                    "Expected an array of " #T);
68                     }
69                 }
70             } else {
71                 SWIG_croak("Type error in argument $argnum of $symname. "
72                            "Expected an array of " #T);
73             }
74         }
75         %typemap(in) const vector<T>& (std::vector<T> temp,
76                                        std::vector<T>* v),
77                      const vector<T>* (std::vector<T> temp,
78                                        std::vector<T>* v) {
79             if (SWIG_ConvertPtr($input,(void **) &v, 
80                                 $1_descriptor,1) != -1) {
81                 $1 = v;
82             } else if (SvROK($input)) {
83                 AV *av = (AV *)SvRV($input);
84                 if (SvTYPE(av) != SVt_PVAV)
85                     SWIG_croak("Type error in argument $argnum of $symname. "
86                                "Expected an array of " #T);
87                 SV **tv;
88                 I32 len = av_len(av) + 1;
89                 T* obj;
90                 for (int i=0; i<len; i++) {
91                     tv = av_fetch(av, i, 0);
92                     if (SWIG_ConvertPtr(*tv, (void **)&obj, 
93                                         $descriptor(T *),0) != -1) {
94                         temp.push_back(*obj);
95                     } else {
96                         SWIG_croak("Type error in argument $argnum of "
97                                    "$symname. "
98                                    "Expected an array of " #T);
99                     }
100                 }
101                 $1 = &temp;
102             } else {
103                 SWIG_croak("Type error in argument $argnum of $symname. "
104                            "Expected an array of " #T);
105             }
106         }
107         %typemap(out) vector<T> {
108             size_t len = $1.size();
109             SV **svs = new SV*[len];
110             for (size_t i=0; i<len; i++) {
111                 T* ptr = new T($1[i]);
112                 svs[i] = sv_newmortal();
113                 SWIG_MakePtr(svs[i], (void*) ptr, 
114                              $descriptor(T *), $shadow|$owner);
115             }
116             AV *myav = av_make(len, svs);
117             delete[] svs;
118             $result = newRV_noinc((SV*) myav);
119             sv_2mortal($result);
120             argvi++;
121         }
122         %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> {
123             {
124                 /* wrapped vector? */
125                 std::vector<T >* v;
126                 if (SWIG_ConvertPtr($input,(void **) &v, 
127                                     $&1_descriptor,0) != -1) {
128                     $1 = 1;
129                 } else if (SvROK($input)) {
130                     /* native sequence? */
131                     AV *av = (AV *)SvRV($input);
132                     if (SvTYPE(av) == SVt_PVAV) {
133                         I32 len = av_len(av) + 1;
134                         if (len == 0) {
135                             /* an empty sequence can be of any type */
136                             $1 = 1;
137                         } else {
138                             /* check the first element only */
139                             T* obj;
140                             SV **tv = av_fetch(av, 0, 0);
141                             if (SWIG_ConvertPtr(*tv, (void **)&obj, 
142                                                 $descriptor(T *),0) != -1)
143                                 $1 = 1;
144                             else
145                                 $1 = 0;
146                         }
147                     }
148                 } else {
149                     $1 = 0;
150                 }
151             }
152         }
153         %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&,
154                                           const vector<T>* {
155             {
156                 /* wrapped vector? */
157                 std::vector<T >* v;
158                 if (SWIG_ConvertPtr($input,(void **) &v, 
159                                     $1_descriptor,0) != -1) {
160                     $1 = 1;
161                 } else if (SvROK($input)) {
162                     /* native sequence? */
163                     AV *av = (AV *)SvRV($input);
164                     if (SvTYPE(av) == SVt_PVAV) {
165                         I32 len = av_len(av) + 1;
166                         if (len == 0) {
167                             /* an empty sequence can be of any type */
168                             $1 = 1;
169                         } else {
170                             /* check the first element only */
171                             T* obj;
172                             SV **tv = av_fetch(av, 0, 0);
173                             if (SWIG_ConvertPtr(*tv, (void **)&obj, 
174                                                 $descriptor(T *),0) != -1)
175                                 $1 = 1;
176                             else
177                                 $1 = 0;
178                         }
179                     }
180                 } else {
181                     $1 = 0;
182                 }
183             }
184         }
185       public:
186         vector(unsigned int size = 0);
187         vector(unsigned int size, const T& value);
188         vector(const vector<T> &);
189
190         unsigned int size() const;
191         bool empty() const;
192         void clear();
193         %rename(push) push_back;
194         void push_back(const T& x);
195         %extend {
196             T pop() throw (std::out_of_range) {
197                 if (self->size() == 0)
198                     throw std::out_of_range("pop from empty vector");
199                 T x = self->back();
200                 self->pop_back();
201                 return x;
202             }
203             T& get(int i) throw (std::out_of_range) {
204                 int size = int(self->size());
205                 if (i>=0 && i<size)
206                     return (*self)[i];
207                 else
208                     throw std::out_of_range("vector index out of range");
209             }
210             void set(int i, const T& x) throw (std::out_of_range) {
211                 int size = int(self->size());
212                 if (i>=0 && i<size)
213                     (*self)[i] = x;
214                 else
215                     throw std::out_of_range("vector index out of range");
216             }
217         }
218     };
219
220     // specializations for pointers
221     template<class T> class vector<T*> {
222         %typemap(in) vector<T*> (std::vector<T*>* v) {
223             int res = SWIG_ConvertPtr($input,(void **) &v, $&1_descriptor,0);
224             if (SWIG_IsOK(res)){
225                 $1 = *v;
226             } else if (SvROK($input)) {
227                 AV *av = (AV *)SvRV($input);
228                 if (SvTYPE(av) != SVt_PVAV)
229                     SWIG_croak("Type error in argument $argnum of $symname. "
230                                "Expected an array of " #T);
231                 I32 len = av_len(av) + 1;
232                 for (int i=0; i<len; i++) {
233                     void *v;
234                     SV **tv = av_fetch(av, i, 0);
235                     int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
236                     if (SWIG_IsOK(res)) {
237                         $1.push_back(%static_cast(v, T *));
238                     } else {
239                         SWIG_croak("Type error in argument $argnum of "
240                                    "$symname. "
241                                    "Expected an array of " #T);
242                     }
243                 }
244             } else {
245                 SWIG_croak("Type error in argument $argnum of $symname. "
246                            "Expected an array of " #T);
247             }
248         }
249         %typemap(in) const vector<T *>& (std::vector<T *> temp,std::vector<T *>* v),
250                      const vector<T *>* (std::vector<T *> temp,std::vector<T *>* v) {
251             int res = SWIG_ConvertPtr($input,(void **) &v, $1_descriptor,0);
252             if (SWIG_IsOK(res)) {
253                 $1 = v;
254             } else if (SvROK($input)) {
255                 AV *av = (AV *)SvRV($input);
256                 if (SvTYPE(av) != SVt_PVAV)
257                     SWIG_croak("Type error in argument $argnum of $symname. "
258                                "Expected an array of " #T);
259                 I32 len = av_len(av) + 1;
260                 for (int i=0; i<len; i++) {
261                     void *v;
262                     SV **tv = av_fetch(av, i, 0);
263                     int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
264                     if (SWIG_IsOK(res)) {
265                         temp.push_back(%static_cast(v, T *));
266                     } else {
267                         SWIG_croak("Type error in argument $argnum of "
268                                    "$symname. "
269                                    "Expected an array of " #T);
270                     }
271                 }
272                 $1 = &temp;
273             } else {
274                 SWIG_croak("Type error in argument $argnum of $symname. "
275                            "Expected an array of " #T);
276             }
277         }
278         %typemap(out) vector<T *> {
279             size_t len = $1.size();
280             SV **svs = new SV*[len];
281             for (size_t i=0; i<len; i++) {
282                 T *x = (($1_type &)$1)[i];
283                 svs[i] = sv_newmortal();
284                 sv_setsv(svs[i], SWIG_NewPointerObj(x, $descriptor(T *), 0));
285             }
286             AV *myav = av_make(len, svs);
287             delete[] svs;
288             $result = newRV_noinc((SV*) myav);
289             sv_2mortal($result);
290             argvi++;
291         }
292         %typecheck(SWIG_TYPECHECK_VECTOR) vector<T *> {
293             {
294                 /* wrapped vector? */
295                 std::vector<T *>* v;
296                 int res = SWIG_ConvertPtr($input,(void **) &v, $&1_descriptor,0);
297                 if (SWIG_IsOK(res)) {
298                     $1 = 1;
299                 } else if (SvROK($input)) {
300                     /* native sequence? */
301                     AV *av = (AV *)SvRV($input);
302                     if (SvTYPE(av) == SVt_PVAV) {
303                         I32 len = av_len(av) + 1;
304                         if (len == 0) {
305                             /* an empty sequence can be of any type */
306                             $1 = 1;
307                         } else {
308                             /* check the first element only */
309                             void *v;
310                             SV **tv = av_fetch(av, 0, 0);
311                             int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
312                             if (SWIG_IsOK(res))
313                                 $1 = 1;
314                             else
315                                 $1 = 0;
316                         }
317                     }
318                 } else {
319                     $1 = 0;
320                 }
321             }
322         }
323         %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T *>&,const vector<T *>* {
324             {
325                 /* wrapped vector? */
326                 std::vector<T *> *v;
327                 int res = SWIG_ConvertPtr($input,%as_voidptrptr(&v), $1_descriptor,0);
328                 if (SWIG_IsOK(res)) {
329                     $1 = 1;
330                 } else if (SvROK($input)) {
331                     /* native sequence? */
332                     AV *av = (AV *)SvRV($input);
333                     if (SvTYPE(av) == SVt_PVAV) {
334                         I32 len = av_len(av) + 1;
335                         if (len == 0) {
336                             /* an empty sequence can be of any type */
337                             $1 = 1;
338                         } else {
339                             /* check the first element only */
340                             void *v;
341                             SV **tv = av_fetch(av, 0, 0);
342                             int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
343                             if (SWIG_IsOK(res))
344                                 $1 = 1;
345                             else
346                                 $1 = 0;
347                         }
348                     }
349                 } else {
350                     $1 = 0;
351                 }
352             }
353         }
354       public:
355         vector(unsigned int size = 0);
356         vector(unsigned int size, T *value);
357         vector(const vector<T *> &);
358
359         unsigned int size() const;
360         bool empty() const;
361         void clear();
362         %rename(push) push_back;
363         void push_back(T *x);
364         %extend {
365             T *pop() throw (std::out_of_range) {
366                 if (self->size() == 0)
367                     throw std::out_of_range("pop from empty vector");
368                 T *x = self->back();
369                 self->pop_back();
370                 return x;
371             }
372             T *get(int i) throw (std::out_of_range) {
373                 int size = int(self->size());
374                 if (i>=0 && i<size)
375                     return (*self)[i];
376                 else
377                     throw std::out_of_range("vector index out of range");
378             }
379             void set(int i, T *x) throw (std::out_of_range) {
380                 int size = int(self->size());
381                 if (i>=0 && i<size)
382                     (*self)[i] = x;
383                 else
384                     throw std::out_of_range("vector index out of range");
385             }
386         }
387     };
388
389
390     // specializations for built-ins
391
392     %define specialize_std_vector(T,CHECK_T,TO_T,FROM_T)
393     template<> class vector<T> {
394         %typemap(in) vector<T> (std::vector<T>* v) {
395             if (SWIG_ConvertPtr($input,(void **) &v, 
396                                 $&1_descriptor,1) != -1){
397                 $1 = *v;
398             } else if (SvROK($input)) {
399                 AV *av = (AV *)SvRV($input);
400                 if (SvTYPE(av) != SVt_PVAV)
401                     SWIG_croak("Type error in argument $argnum of $symname. "
402                                "Expected an array of " #T);
403                 SV **tv;
404                 I32 len = av_len(av) + 1;
405                 for (int i=0; i<len; i++) {
406                     tv = av_fetch(av, i, 0);
407                     if (CHECK_T(*tv)) {
408                         $1.push_back((T)TO_T(*tv));
409                     } else {
410                         SWIG_croak("Type error in argument $argnum of "
411                                    "$symname. "
412                                    "Expected an array of " #T);
413                     }
414                 }
415             } else {
416                 SWIG_croak("Type error in argument $argnum of $symname. "
417                            "Expected an array of " #T);
418             }
419         }
420         %typemap(in) const vector<T>& (std::vector<T> temp,
421                                        std::vector<T>* v),
422                      const vector<T>* (std::vector<T> temp,
423                                        std::vector<T>* v) {
424             if (SWIG_ConvertPtr($input,(void **) &v, 
425                                 $1_descriptor,1) != -1) {
426                 $1 = v;
427             } else if (SvROK($input)) {
428                 AV *av = (AV *)SvRV($input);
429                 if (SvTYPE(av) != SVt_PVAV)
430                     SWIG_croak("Type error in argument $argnum of $symname. "
431                                "Expected an array of " #T);
432                 SV **tv;
433                 I32 len = av_len(av) + 1;
434                 for (int i=0; i<len; i++) {
435                     tv = av_fetch(av, i, 0);
436                     if (CHECK_T(*tv)) {
437                         temp.push_back((T)TO_T(*tv));
438                     } else {
439                         SWIG_croak("Type error in argument $argnum of "
440                                    "$symname. "
441                                    "Expected an array of " #T);
442                     }
443                 }
444                 $1 = &temp;
445             } else {
446                 SWIG_croak("Type error in argument $argnum of $symname. "
447                            "Expected an array of " #T);
448             }
449         }
450         %typemap(out) vector<T> {
451             size_t len = $1.size();
452             SV **svs = new SV*[len];
453             for (size_t i=0; i<len; i++) {
454                 svs[i] = sv_newmortal();
455                 FROM_T(svs[i], $1[i]);
456             }
457             AV *myav = av_make(len, svs);
458             delete[] svs;
459             $result = newRV_noinc((SV*) myav);
460             sv_2mortal($result);
461             argvi++;
462         }
463         %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> {
464             {
465                 /* wrapped vector? */
466                 std::vector<T >* v;
467                 if (SWIG_ConvertPtr($input,(void **) &v, 
468                                     $&1_descriptor,0) != -1) {
469                     $1 = 1;
470                 } else if (SvROK($input)) {
471                     /* native sequence? */
472                     AV *av = (AV *)SvRV($input);
473                     if (SvTYPE(av) == SVt_PVAV) {
474                         I32 len = av_len(av) + 1;
475                         if (len == 0) {
476                             /* an empty sequence can be of any type */
477                             $1 = 1;
478                         } else {
479                             /* check the first element only */
480                             SV **tv = av_fetch(av, 0, 0);
481                             if (CHECK_T(*tv))
482                                 $1 = 1;
483                             else
484                                 $1 = 0;
485                         }
486                     }
487                 } else {
488                     $1 = 0;
489                 }
490             }
491         }
492         %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&,
493                                           const vector<T>* {
494             {
495                 /* wrapped vector? */
496                 std::vector<T >* v;
497                 if (SWIG_ConvertPtr($input,(void **) &v, 
498                                     $1_descriptor,0) != -1) {
499                     $1 = 1;
500                 } else if (SvROK($input)) {
501                     /* native sequence? */
502                     AV *av = (AV *)SvRV($input);
503                     if (SvTYPE(av) == SVt_PVAV) {
504                         I32 len = av_len(av) + 1;
505                         if (len == 0) {
506                             /* an empty sequence can be of any type */
507                             $1 = 1;
508                         } else {
509                             /* check the first element only */
510                             SV **tv = av_fetch(av, 0, 0);
511                             if (CHECK_T(*tv))
512                                 $1 = 1;
513                             else
514                                 $1 = 0;
515                         }
516                     }
517                 } else {
518                     $1 = 0;
519                 }
520             }
521         }
522       public:
523         vector(unsigned int size = 0);
524         vector(unsigned int size, T value);
525         vector(const vector<T> &);
526
527         unsigned int size() const;
528         bool empty() const;
529         void clear();
530         %rename(push) push_back;
531         void push_back(T x);
532         %extend {
533             T pop() throw (std::out_of_range) {
534                 if (self->size() == 0)
535                     throw std::out_of_range("pop from empty vector");
536                 T x = self->back();
537                 self->pop_back();
538                 return x;
539             }
540             T get(int i) throw (std::out_of_range) {
541                 int size = int(self->size());
542                 if (i>=0 && i<size)
543                     return (*self)[i];
544                 else
545                     throw std::out_of_range("vector index out of range");
546             }
547             void set(int i, T x) throw (std::out_of_range) {
548                 int size = int(self->size());
549                 if (i>=0 && i<size)
550                     (*self)[i] = x;
551                 else
552                     throw std::out_of_range("vector index out of range");
553             }
554         }
555     };
556     %enddef
557
558     specialize_std_vector(bool,SvIOK,SvIVX,sv_setiv);
559     specialize_std_vector(char,SvIOK,SvIVX,sv_setiv);
560     specialize_std_vector(int,SvIOK,SvIVX,sv_setiv);
561     specialize_std_vector(short,SvIOK,SvIVX,sv_setiv);
562     specialize_std_vector(long,SvIOK,SvIVX,sv_setiv);
563     specialize_std_vector(unsigned char,SvIOK,SvIVX,sv_setiv);
564     specialize_std_vector(unsigned int,SvIOK,SvIVX,sv_setiv);
565     specialize_std_vector(unsigned short,SvIOK,SvIVX,sv_setiv);
566     specialize_std_vector(unsigned long,SvIOK,SvIVX,sv_setiv);
567     specialize_std_vector(float,SvNIOK,SwigSvToNumber,sv_setnv);
568     specialize_std_vector(double,SvNIOK,SwigSvToNumber,sv_setnv);
569     specialize_std_vector(std::string,SvPOK,SwigSvToString,SwigSvFromString);
570 }
571