Custom key type implementation
!> Example module demonstrating how a custom key-type
!> can be made.
!>
!> See README.md for an explanation
!>
module my_key_type
use iso_fortran_env, only: int64
use fhash_key_base, only: fhash_key_t
use fhash_fnv, only: fnv_1a
implicit none
private
public :: string_t, key_string_t
public :: fhash_key
!> The custom type for which we wish to create a key
type :: string_t
character(:), allocatable :: s
end type string_t
!> A key type container for our custom type
type, extends(fhash_key_t) :: key_string_t
type(string_t), allocatable :: value(:)
contains
procedure :: hash => key_hash_string_t
procedure :: equals => key_equals_string_t
procedure, pass :: to_string => key_to_string
end type key_string_t
!> Override the existing `fhash_key` interface to additionally
!> support our custom key type
interface fhash_key
module procedure :: key_from_string_t
end interface fhash_key
contains
!> Implements equality operator for custom key type.
!>
!> NB. Keys of different types are always not equal.
!>
pure function key_equals_string_t(key1,key2) result(keys_equal)
class(key_string_t), intent(in) :: key1
class(fhash_key_t), intent(in) :: key2
logical :: keys_equal
integer :: i
keys_equal = .false.
select type(k2=>key2)
type is (key_string_t)
if (size(key1%value) /= size(k2%value)) return
do i=1,size(key1%value)
if (key1%value(i)%s /= k2%value(i)%s) then
return
end if
end do
keys_equal = .true.
return
end select
end function key_equals_string_t
!> Implements hashing of the custom key type.
!>
!> NB. Elementary hash function `fnv_1a` provides support for
!> default scalar characters and 32bit/64bit scalar and 1D integers
!>
pure function key_hash_string_t(key) result(hash)
class(key_string_t), intent(in) :: key
integer(int64) :: hash
integer :: i
do i=1,size(key%value)
if (i == 1) then
hash = fnv_1a(key%value(i)%s)
else
hash = fnv_1a(hash, key%value(i)%s)
end if
end do
end function key_hash_string_t
!> Generate string representation of hash
pure function key_to_string(key) result(str)
class(key_string_t), intent(in) :: key
character(:), allocatable :: str
integer :: i
str = ''
do i=1,size(key%value)
str = str//','//key%value(i)%s
end do
end function key_to_string
!> Helper function to create new key container from
!> some set of inputs
function key_from_string_t(source) result(key)
type(string_t), intent(in) :: source(:)
type(key_string_t) :: key
key%value = source
end function key_from_string_t
end module my_key_type