PageRenderTime 38ms CodeModel.GetById 17ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 1ms

/trunk/Lib/perl5/std_vector.i

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