Skip to content

Commit 4f03616

Browse files
authored
Merge pull request #151 from swig-fortran/std-lib-enhance
Improve, fix, and extend standard library
2 parents 6787b6e + 8230484 commit 4f03616

File tree

13 files changed

+235
-46
lines changed

13 files changed

+235
-46
lines changed

Examples/test-suite/abstract_signature.i

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) abstract_foo; // Ruby, wrong class name
44
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) abstract_bar; // Ruby, wrong class name
5+
%warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) meth; // Fortran prevents overloaded methods from overriding a base class non-overloaded method
56

67
%inline %{
78
class abstract_foo

Examples/test-suite/constant_directive.i

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
#ifdef SWIGOCAML
66
%warnfilter(SWIGWARN_PARSE_KEYWORD) val;
7+
#elif SWIGFORTRAN
8+
// Can't natively wrap function pointers with nonnative return type
9+
%warnfilter(SWIGWARN_LANG_NATIVE_UNIMPL,SWIGWARN_TYPEMAP_UNDEF) TYPE1FPTR1_CONSTANT1;
710
#endif
811

912
%inline %{

Examples/test-suite/fortran/Makefile.in

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ FAILING_CPP_TESTS += \
5252
smart_pointer_member \
5353
smart_pointer_template_defaults_overload \
5454
typedef_classforward_same_name \
55-
li_std_map \
5655
cpp11_result_of \
5756
cpp11_rvalue_reference2 \
5857
cpp11_rvalue_reference3 \
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
! File : li_std_map_runme.f90
2+
3+
#include "fassert.h"
4+
5+
program li_std_map_runme
6+
use ISO_C_BINDING
7+
implicit none
8+
9+
call test_map_int_int
10+
call test_map_string_int
11+
contains
12+
13+
subroutine test_map_int_int
14+
use ISO_C_BINDING
15+
! Note that the test instantiates *multiset* as a set_int
16+
use li_std_map, only : MapIntInt => IntIntMap
17+
implicit none
18+
type(MapIntInt) :: m
19+
integer :: num_erased
20+
logical :: inserted = .false.
21+
22+
m = MapIntInt()
23+
ASSERT(m%empty())
24+
25+
call m%insert(10, 4)
26+
call m%insert(3, 5, inserted)
27+
ASSERT(inserted .eqv. .true.)
28+
ASSERT(m%size() == 2)
29+
ASSERT(m%count(3) == 1)
30+
ASSERT(m%count(5) == 0)
31+
32+
! Insertion of existing element will *not* replace value
33+
call m%insert(3, 6, inserted)
34+
ASSERT(inserted .eqv. .false.)
35+
ASSERT(m%count(3) == 1)
36+
ASSERT(m%size() == 2)
37+
ASSERT(m%get(3) == 5)
38+
39+
! Use "set" method to unconditionally assign
40+
call m%set(3, 6)
41+
ASSERT(m%get(3) == 6)
42+
43+
call m%erase(10)
44+
ASSERT(m%size() == 1)
45+
ASSERT(m%count(10) == 0)
46+
47+
call m%erase(3, num_erased)
48+
ASSERT(num_erased == 1)
49+
ASSERT(m%count(3) == 0)
50+
51+
call m%release()
52+
end subroutine
53+
54+
subroutine test_map_string_int
55+
use ISO_C_BINDING
56+
use li_std_map, only : MapStringInt => StringIntMap
57+
implicit none
58+
type(MapStringInt) :: m
59+
60+
m = MapStringInt()
61+
ASSERT(m%empty())
62+
63+
call m%insert("yoohoo", 10)
64+
call m%insert("howdy", 5)
65+
ASSERT(m%size() == 2)
66+
ASSERT(m%count("yoohoo") == 1)
67+
ASSERT(m%count("hiya") == 0)
68+
ASSERT(m%get("yoohoo") == 10)
69+
call m%release()
70+
end subroutine
71+
72+
end program
73+

Examples/test-suite/fortran/li_std_set_runme.F90

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,20 @@ subroutine test_set_string
5252
use li_std_set, only : set_string
5353
implicit none
5454
type(set_string) :: s
55+
logical :: inserted = .false.
5556

5657
s = set_string()
5758
ASSERT(s%empty())
5859

5960
call s%insert("yoohoo")
60-
call s%insert("howdy")
61+
call s%insert("howdy", inserted)
62+
ASSERT(inserted .eqv. .true.)
6163
ASSERT(s%size() == 2)
6264
ASSERT(s%count("yoohoo") == 1)
6365
ASSERT(s%count("hiya") == 0)
6466

65-
call s%insert("howdy")
67+
call s%insert("howdy", inserted)
68+
ASSERT(inserted .eqv. .false.)
6669
ASSERT(s%count("howdy") == 1)
6770
ASSERT(s%size() == 2)
6871

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
! File : li_std_string_runme.f90
2+
3+
#include "fassert.h"
4+
5+
program li_std_string_runme
6+
use li_std_string
7+
use ISO_C_BINDING
8+
implicit none
9+
character(kind=C_CHAR, len=*), parameter :: mystring = "howdy!"
10+
character(kind=C_CHAR, len=:), allocatable :: actual
11+
type(swigtype_p_std__string) :: anonymous_string
12+
13+
allocate(actual, source=test_value(mystring))
14+
ASSERT(actual == mystring)
15+
deallocate(actual)
16+
17+
actual = test_const_reference(mystring)
18+
ASSERT(actual == mystring)
19+
deallocate(actual)
20+
21+
call test_pointer(anonymous_string)
22+
23+
anonymous_string = test_pointer_out()
24+
end program
25+

Examples/test-suite/fortran_ownership.i

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,18 @@ void do_nothing(TemplTricky<int>) {};
7676
%}
7777

7878
%template(TemplTrickyInt) myns::TemplTricky<int>;
79+
80+
// Test autofree declaration *before* including std:string
81+
%fortran_autofree_rvalue(std::string)
82+
namespace std {
83+
class string {
84+
};
85+
}
86+
87+
%include <std_string.i>
88+
89+
%inline %{
90+
std::string str_value(std::string s) { return s; }
91+
const std::string& str_cref(const std::string& s) { return s; }
92+
std::string& str_ref(std::string& s) { return s; }
93+
%}

Lib/fortran/std_map.i

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,60 @@
22
* std_map.i
33
* ------------------------------------------------------------------------- */
44

5+
%include "std_common.i"
6+
57
%{
68
#include <map>
79
%}
8-
#error "std::map support is not yet implemented"
910

11+
%define %swig_std_map(_Key, _Value, _Compare)
12+
13+
public:
14+
typedef size_t size_type;
15+
typedef ptrdiff_t difference_type;
16+
typedef _Key key_type;
17+
typedef _Value mapped_type;
18+
typedef std::pair<const _Key, _Value> value_type;
19+
typedef value_type *pointer;
20+
typedef const value_type *const_pointer;
21+
typedef value_type &reference;
22+
typedef const value_type &const_reference;
23+
24+
map();
25+
26+
// - Use native Fortran integers in proxy code
27+
%apply int FORTRAN_INT {size_type};
28+
29+
bool empty() const;
30+
size_type size() const;
31+
void clear();
32+
33+
%fortransubroutine erase;
34+
35+
size_type erase(const key_type &x);
36+
size_type count(const key_type &x) const;
37+
38+
%fortransubroutine insert;
39+
40+
%extend {
41+
bool insert(const _Key& k, const _Value& v) {
42+
std::pair<std::map<_Key, _Value, _Compare >::iterator, bool> result = $self->insert(std::pair<_Key, _Value>(k, v));
43+
return result.second;
44+
}
45+
46+
const _Value& get(const _Key& k) {
47+
return (*$self)[k];
48+
}
49+
void set(const _Key& k, const _Value& v) {
50+
(*$self)[k] = v;
51+
}
52+
}
53+
54+
%enddef
55+
56+
namespace std {
57+
template<class _Key, class _Value, class _Compare = std::less<_Key > >
58+
class map {
59+
%swig_std_map(_Key, _Value, _Compare);
60+
};
61+
} // namespace std

Lib/fortran/std_multiset.i

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@
77

88
%include "std_set.i"
99

10+
%define %swig_std_multiset(_Key, _Compare, _Alloc)
11+
%swig_std_setcommon(multiset, _Key, _Compare, _Alloc)
12+
13+
void insert(const_reference x);
14+
%enddef
15+
1016
namespace std {
1117
template<class _Key, class _Compare = std::less<_Key>, class _Alloc = std::allocator<_Key> >
1218
class multiset {
13-
SWIG_STD_SET_COMMON(multiset, _Key, _Compare, _Alloc)
19+
%swig_std_multiset( _Key, _Compare, _Alloc)
1420
};
1521
} // end namespace std
1622

Lib/fortran/std_set.i

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
#include <set>
99
%}
1010

11-
%define SWIG_STD_SET_COMMON(CLASS, _Key, _Compare, _Alloc)
11+
// methods used by both set *and* multiset
12+
%define %swig_std_setcommon(CLASS, _Key, _Compare, _Alloc)
1213

1314
public:
1415
// Typedefs
@@ -36,14 +37,25 @@ public:
3637

3738
size_type erase(const key_type& x);
3839
size_type count(const key_type& x) const;
39-
void insert(const_reference x);
40+
%enddef
41+
42+
%define %swig_std_set(_Key, _Compare, _Alloc)
43+
%swig_std_setcommon(set, _Key, _Compare, _Alloc)
44+
45+
%fortransubroutine insert;
4046

47+
%extend {
48+
bool insert(const_reference x) {
49+
std::pair<std::set<_Key, _Compare, _Alloc >::iterator, bool> result = $self->insert(x);
50+
return result.second;
51+
}
52+
}
4153
%enddef
4254

4355
namespace std {
4456
template<class _Key, class _Compare = std::less<_Key>, class _Alloc = std::allocator<_Key> >
4557
class set {
46-
SWIG_STD_SET_COMMON(set, _Key, _Compare, _Alloc)
58+
%swig_std_set(_Key, _Compare, _Alloc)
4759
};
4860
} // end namespace std
4961

0 commit comments

Comments
 (0)