Skip to content

Commit ee1d8b0

Browse files
authored
Add std::map (#18)
* Update macros and regenerate for latest SWIG * Add map and documentation
1 parent d8e6a25 commit ee1d8b0

16 files changed

+2162
-68
lines changed

CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ endif()
213213
flibcpp_add_module(flc_algorithm)
214214
target_link_libraries(flc_algorithm flc_random flc)
215215

216+
flibcpp_add_module(flc_map)
217+
target_link_libraries(flc_map flc flc_string)
218+
216219
flibcpp_add_module(flc_random)
217220
target_link_libraries(flc_random flc)
218221

doc/modules/map.rst

+59-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,65 @@
88
Map
99
***
1010

11-
Maps, sorted dictionaries mapping keys to values, are not yet implemented.
11+
Maps are sorted dictionaries mapping keys to values. Currently they have
12+
limited functionality and few instantiations: maps of ints to ints and of
13+
strings to strings.
14+
15+
Basic functionality
16+
===================
17+
18+
All map types support the following basic operations.
19+
20+
Construction and destruction
21+
----------------------------
22+
23+
Like other wrapped C++ classes in Flibcpp, maps are
24+
constructed using an interface function. The default constructor is an empty
25+
map. Maps are destroyed using the ``release`` type-bound subroutine.
26+
27+
Modification
28+
------------
29+
30+
The contents of the map can be changed with the following methods:
31+
32+
``insert``:
33+
Add a new key-value pair to the map. If the key already exists, the value in
34+
the map will remain unchanged. An optional ``logical`` parameter can be
35+
passed that will be set to ``.true.`` if insertion was successful and
36+
``.false.`` if the key already existed.
37+
38+
``set``:
39+
Assign the given value to the key, regardless of whether the value already
40+
existed.
41+
42+
``get``:
43+
Return the value for the specified key, creating it with a default value
44+
(zero for numeric types, empty for string types) if it does not exist.
45+
46+
``clear``:
47+
Remove all items from the map.
48+
49+
The ``size`` method returns the number of elements, and ``count`` will return
50+
the number of elements with the given key.
51+
52+
Here's an example of creating, modifying, and destroying a map::
53+
54+
use flc_map, only : Map => MapIntInt
55+
type(Map) :: m
56+
logical :: inserted = .false.
57+
integer(C_INT) :: value
58+
m = Map()
59+
call m%insert(123, 456)
60+
call m%insert(123, 567, inserted) ! inserted = false, value unchanged
61+
call m%set(123, 567) ! value is changed
62+
value = m%get(911) ! implicitly created value of zero
63+
call m%erase(911)
64+
call m%release()
65+
66+
Iteration
67+
---------
68+
69+
Iterating over a map to determine its contents is not yet supported.
1270

1371
.. ############################################################################
1472
.. end of doc/modules/map.rst

doc/modules/set.rst

+10-4
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,17 @@ an element to and removing an element from the set. A ``clear`` subroutine
3131
removes all elements from the set.
3232

3333
The ``size`` method returns the number of elements, and ``count`` will return
34-
the number of elements of a given value
34+
the number of elements of a given value.
3535

3636
Here's an example of creating, modifying, and destroying a set::
3737

38-
use flc_set, only : Set => SetInt4
38+
use flc_set, only : Set => SetInt
3939
type(Set) :: s
40+
logical :: inserted
4041
s = Set()
4142
call s%insert(2)
42-
call s%insert(3) ! Set has 2 elements
43-
call s%insert(3) ! Duplicate element, ignored
43+
call s%insert(3, inserted) ! Set has 2 elements, inserted => true
44+
call s%insert(3, inserted) ! Duplicate element, ignored; inserted => false
4445
call s%erase(2) ! Remove 2 from the set
4546
call s%erase(1) ! Nonexistent set element, ignored
4647
write(0,*) "Number of 3s in the set:" s%count(3)
@@ -76,6 +77,11 @@ newly allocated ``Set`` instances and do not modify the original sets.
7677
``includes``: :math:`A \supseteq B`
7778
Return whether all elements of the other set are in the original set.
7879

80+
Iteration
81+
---------
82+
83+
Iterating over a set to determine its contents is not yet supported.
84+
7985
Numeric sets
8086
===============
8187

include/flc_map.i

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*!
2+
* \file flc_map.i
3+
*
4+
* Copyright (c) 2019 Oak Ridge National Laboratory, UT-Battelle, LLC.
5+
* Distributed under an MIT open source license: see LICENSE for details.
6+
*/
7+
8+
%module "flc_map"
9+
%include "import_flc.i"
10+
%flc_add_header
11+
12+
%include <std_map.i>
13+
14+
/* -------------------------------------------------------------------------
15+
* Numeric maps
16+
* ------------------------------------------------------------------------- */
17+
18+
%template(MapIntInt) std::map<int, int>;
19+
20+
/* -------------------------------------------------------------------------
21+
* String maps
22+
* ------------------------------------------------------------------------- */
23+
24+
%fortran_autofree_rvalue(std::map<std::string, int>);
25+
%fortran_autofree_rvalue(std::map<std::string, std::string>);
26+
27+
%include <std_string.i>
28+
%import "flc_string.i"
29+
%template(MapStringInt) std::map<std::string, int>;
30+
%template(MapStringString) std::map<std::string, std::string>;

include/flc_set.i

+10-11
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
} // end %extend
4646
%enddef
4747

48-
%define %flc_extend_set_pod(CTYPE)
48+
%define %flc_std_set_extend_pod(CTYPE)
49+
%extend {
4950
%apply (const SWIGTYPE *DATA, ::size_t SIZE)
5051
{ (const CTYPE* DATA, size_type SIZE) };
5152

@@ -58,16 +59,15 @@
5859
void insert(const CTYPE* DATA, size_type SIZE) {
5960
$self->insert(DATA, DATA + SIZE);
6061
}
62+
}
6163
%enddef
6264

6365
/* ------------------------------------------------------------------------- */
6466
/*! \def %specialize_std_set_pod
6567
*
6668
* Inject member functions and typemaps for POD classes.
6769
*
68-
* These provide an efficient constructor from a Fortan array view. It also
69-
* offers a "view" functionality for getting an array pointer to the
70-
* set-owned data.
70+
* These provide an efficient constructor from a Fortan array view.
7171
*
7272
* This definition is considered part of the \em public API so that downstream
7373
* apps that generate FLC-based bindings can instantiate their own POD sets.
@@ -79,11 +79,8 @@
7979

8080
namespace std {
8181
template<> class set<T> {
82-
83-
SWIG_STD_SET_COMMON(set, T, std::less<T>, std::allocator<T>)
84-
%extend {
85-
%flc_extend_set_pod(T)
86-
}
82+
%swig_std_set(T, std::less<T>, std::allocator<T>)
83+
%flc_std_set_extend_pod(T)
8784
};
8885
}
8986
%enddef
@@ -131,8 +128,10 @@ static bool flc_set_includes(const Set_t& left, const Set_t& right)
131128

132129
// Allow direct insertion of a wrapped std::string
133130
%extend std::set<std::string> {
134-
void insert_ref(std::string& str) {
135-
$self->insert(str);
131+
%apply SWIGTYPE& { const std::string& STR_CLASS };
132+
133+
void insert_ref(const std::string& STR_CLASS) {
134+
$self->insert(STR_CLASS);
136135
}
137136
}
138137

include/flc_vector.i

+18-18
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
* Macro definitions
1616
* ------------------------------------------------------------------------- */
1717

18-
%define %flc_extend_vector_pod(CTYPE)
18+
%define %flc_std_vector_extend_pod(CTYPE)
19+
%extend {
1920
%apply (const SWIGTYPE *DATA, ::size_t SIZE)
2021
{ (const CTYPE* DATA, size_type SIZE) };
2122

@@ -40,48 +41,47 @@
4041
vector<CTYPE>& view() {
4142
return *$self;
4243
}
44+
}
4345
%enddef
4446

4547
/* ------------------------------------------------------------------------- */
46-
/*! \def %specialize_std_vector_pod
48+
/*! \def %flc_template_std_vector_pod
4749
*
48-
* Inject member functions and typemaps for POD classes.
50+
* Inject member functions and typemaps for POD classes, and instantiate.
4951
*
50-
* These provide an efficient constructor from a Fortan array view. It also
51-
* offers a "view" functionality for getting an array pointer to the
52+
* The added methods provide an efficient constructor from a Fortan array view.
53+
* It also offers a "view" functionality for getting an array pointer to the
5254
* vector-owned data.
5355
*
5456
* This definition is considered part of the \em public API so that downstream
5557
* apps that generate FLC-based bindings can instantiate their own POD vectors.
5658
*/
57-
%define %specialize_std_vector_pod(T)
59+
%define %flc_template_std_vector_pod(NAME, T)
5860

5961
// Automatically free temporary vectors as appropriate
6062
%fortran_autofree_rvalue(std::vector<T>);
6163

6264
namespace std {
6365
template<> class vector<T> {
6466

65-
SWIG_STD_VECTOR_COMMON(T, const T&)
66-
SWIG_STD_VECTOR_REF(T)
67-
%extend {
68-
%flc_extend_vector_pod(T)
69-
}
67+
%swig_std_vector(T, const T&)
68+
%swig_std_vector_extend_ref(T)
69+
%flc_std_vector_extend_pod(T)
7070
};
7171
}
72+
73+
// Instantiate the template
74+
%template(NAME) std::vector<T>;
75+
7276
%enddef
7377

7478
/* -------------------------------------------------------------------------
7579
* Numeric vectors
7680
* ------------------------------------------------------------------------- */
7781

78-
%specialize_std_vector_pod(int32_t)
79-
%specialize_std_vector_pod(int64_t)
80-
%specialize_std_vector_pod(double)
81-
82-
%template(VectorInt4) std::vector<int32_t>;
83-
%template(VectorInt8) std::vector<int64_t>;
84-
%template(VectorReal8) std::vector<double>;
82+
%flc_template_std_vector_pod(VectorInt4, int32_t)
83+
%flc_template_std_vector_pod(VectorInt8, int64_t)
84+
%flc_template_std_vector_pod(VectorReal8, double)
8585

8686
/* -------------------------------------------------------------------------
8787
* String vectors

src/flc_algorithm.f90

+2-2
Original file line numberDiff line numberDiff line change
@@ -778,8 +778,8 @@ subroutine swigf_sort__SWIG_7(data, cmp)
778778

779779
subroutine SWIGTM_fout_bool(imout, fout)
780780
use, intrinsic :: ISO_C_BINDING
781-
integer(kind=C_INT), intent(IN) :: imout
782-
logical, intent(OUT) :: fout
781+
integer(kind=C_INT), intent(in) :: imout
782+
logical, intent(out) :: fout
783783
! TODO: fout = (imout /= 0) ???
784784
if (imout /= 0) then
785785
fout = .true.

0 commit comments

Comments
 (0)