The map_any_type
module defines a map data structure or associative
array which stores (key, value) pairs as the elements of the structure.
The keys are unique and are regarded as mapping or indexing to the value
associated with the key. In this implementation keys are character strings
but the values may be a scalar value of any intrinsic or derived type. An
associated iterator derived type is also defined which gives sequential
access to all elements of the map structure.
use map_any_type
type(map_any) :: map
type(map_any_iterator) :: iter
The derived type map_any
defines a map data structure which stores
(key, value) pairs. The keys are unique character strings that map (or index)
to the value associated with the key. Values may be a scalar of any intrinsic
or derived type. There are limitations, however, with some derived type values;
see the caution below. The derived type has the following properties:
map_any
objects are properly finalized when deallocated or when they
otherwise cease to exist.
Scalar assignment is defined for map_any
objects with the expected
semantics. The contents of the lhs map are first cleared, and then the lhs
map defined with the same (key, value) pairs as the rhs map, becoming an
independent copy of the rhs map; but see the caution below for derived
type values.
The structure constructor map_any()
evaluates to an empty map,
and map_any
variables come into existence as empty maps.
insert(key, value)
Add the specified key and associated value to the map. If the mapping
already exists, its value is replaced with the specified one. key
is
a character string and value
may be a scalar of any intrinsic or
derived type. A copy of value
is stored in the map; see the caution
below for derived type values.
remove(key)
Remove the specified key from the map and deallocate the associated value. If the mapping does not exist, the map is unchanged.
clear()
Remove all elements from the map.
mapped(key)
Return true if a mapping for the specified key exists.
value(key)
Return a class(*)
pointer to the mapped value for the specified
key, or a null pointer if the map does not contain the key.
size()
Return the number of elements in the map.
empty()
Return true if the map contains no elements; otherwise false.
Caution
Derived type values with pointer components, direct or indirect, should
only be used advisedly. The map values are sourced-allocation copies of
the values passed to the insert
procedure, and this only makes a
shallow copy of any pointer component. The original pointer and its
copy will have the same target; no copy of the target is made. This also
applies to map assignment where the values in the lhs map are
sourced-allocation copies of the values in the rhs map.
The derived type map_any_iterator
provides a means of iterating through
the elements of a map_any
object, sequentially visiting each element of
a map once and only once. A defined map_any_iterator
object is positioned
at a particular element of its associated map, or at a pseudo-position
the-end, and can be queried for the key and value of that element.
The structure constructor map_any_iterator(map)
evaluates to an iterator
positioned at the the initial element of the specified map
, or the-end if
map
is empty, and map_any_iterator
variables are initialized by
assignment from such structure constructor expressions; for example,
type(map_any) :: map
type(map_any_iterator) :: iter
iter = map_any_iterator(map)
More generally, scalar assignment is defined for map_any_iterator
objects.
The lhs iterator becomes associated with the same map as the rhs iterator, and
is positioned at the same element. Subsequent changes to one iterator do not
affect the other.
next()
Advance the iterator to the next element in the map, or to the-end if there are no more elements remaining to be visited. This call has no effect if the iterator is already positioned at the-end.
at_end()
Return true if the iterator is positioned at the-end; otherwise false.
key()
Return the character string key for the current map element. The iterator must not be positioned at the-end.
value()
Return a class(*)
pointer to the value of the current map element.
The iterator must not be positioned at the-end.
use map_any_type
type(map_any) :: map, map_copy
type(map_any_iterator) :: iter
class(*), pointer :: value
type point
real x, y
end type
!! Maps come into existence well-defined and empty.
if (.not.map%empty()) print *, 'error: map is not empty!'
!! Insert some elements into the map; note the different types.
call map%insert('page', 3)
call map%insert('size', 1.4)
call map%insert('color', 'black')
call map%insert('origin', point(1.0, 2.0))
!! Replace an existing mapping with a new value of different type.
call map%insert('size', 'default')
!! Remove a mapping.
call map%remove('color')
if (map%mapped('color')) print *, 'error: mapping not removed!'
!! Retrieve a specific value.
value => map%value('origin')
!! Write the contents, using an iterator to access all elements.
iter = map_any_iterator(map)
do while (.not.iter%at_end())
select type (uptr => iter%value())
type is (integer)
print *, iter%key(), ' = ', uptr
type is (real)
print *, iter%key(), ' = ', uptr
type is (character(*))
print *, iter%key(), ' = ', uptr
type is (point)
print *, iter%key(), ' = ', uptr
end select
call iter%next
end do
!! Make a copy of the map.
map_copy = map
!! Delete the contents of map; map_copy is unchanged.
call map%clear
if (map%size() /= 0) print *, 'error: map size is not 0!'
if (map_copy%empty()) print *, 'error: map_copy is empty!'