1/* -----------------------------------------------------------------------------
2 * rubycontainer_extended.swg
3 *
4 * This file contains additional functions that make containers
5 * behave closer to ruby primitive types.
6 * However, some of these functions place some restrictions on
7 * the underlying object inside of the container and the iterator
8 * (that it has to have an == comparison function, that it has to have
9 * an = assignment operator, etc).
10 * ----------------------------------------------------------------------------- */
11
12/**
13 * Macro used to add extend functions that require operator== in object.
14 *
15 * @param Container    STL container
16 * @param Type         class inside container
17 *
18 */
19%define %swig_container_with_equal_operator( Container, Type )
20
21  VALUE __delete__( const Type& val ) {
22    VALUE r = Qnil;
23    Container<Type >::iterator e = $self->end();
24    Container<Type >::iterator i = std::remove( $self->begin(), e, val );
25    // remove dangling elements now
26    $self->erase( i, e );
27
28    if ( i != e )
29      r = swig::from< Type >( val );
30    else if ( rb_block_given_p() )
31      r = rb_yield(Qnil);
32    return r;
33  }
34
35%enddef  // end of  %swig_container_with_equal_operator
36
37
38
39
40/**
41 * Macro used to add extend functions that require the assignment
42 * operator (ie. = ) of contained class
43 *
44 * @param Container    STL container
45 * @param Type         class inside container
46 *
47 */
48
49%define %swig_container_with_assignment( Container, Type )
50
51
52  //
53  // map!  -- the equivalent of std::transform
54  //
55  Container< Type >* map_bang() {
56
57    if ( !rb_block_given_p() )
58      rb_raise( rb_eArgError, "No block given" );
59
60    VALUE r = Qnil;
61    Container< Type >::iterator i = $self->begin();
62    Container< Type >::iterator e = $self->end();
63
64    try {
65      for ( ; i != e; ++i )
66	{
67	  r = swig::from< Type >( *i );
68	  r = rb_yield( r );
69	  *i = swig::as< Type >( r );
70	}
71    }
72    catch ( const std::invalid_argument& )
73      {
74	rb_raise(rb_eTypeError,
75		 "Yield block did not return a valid element for " "Container");
76      }
77
78    return $self;
79  }
80
81
82%enddef  // end of  %swig_container_with_assignment
83
84
85
86
87
88/**
89 * Macro used to add all extended functions to a container
90 *
91 * @param Container    STL container
92 * @param Type         class inside container
93 *
94 */
95%define %swig_container_extend( Container, Type )
96
97%extend Container< Type > {
98
99  %swig_container_with_assignment( %arg(Container), Type );
100  %swig_container_with_equal_operator( %arg(Container), Type );
101
102}
103
104%enddef
105
106
107/**
108 * Private macro used to add all extended functions to C/C++
109 * primitive types
110 *
111 * @param Container an STL container, like std::vector (with no class template)
112 *
113 */
114%define %__swig_container_extend_primtypes( Container )
115
116%swig_container_extend( %arg( Container ), bool );
117%swig_container_extend( %arg( Container ), char );
118%swig_container_extend( %arg( Container ), short );
119%swig_container_extend( %arg( Container ), int );
120%swig_container_extend( %arg( Container ), unsigned short );
121%swig_container_extend( %arg( Container ), unsigned int );
122%swig_container_extend( %arg( Container ), float );
123%swig_container_extend( %arg( Container ), double );
124%swig_container_extend( %arg( Container ), std::complex );
125%swig_container_extend( %arg( Container ), std::string );
126%swig_container_extend( %arg( Container ), swig::GC_VALUE );
127
128%enddef
129
130
131%__swig_container_extend_primtypes( std::vector );
132%__swig_container_extend_primtypes( std::deque );
133%__swig_container_extend_primtypes( std::list );
134
135