10#include "scaleFElib.h"
30 procedure(key_equal_func),
private,
deferred :: key_equal
31 generic,
public ::
operator(==) => key_equal
45 class(*),
allocatable :: key
46 class(*),
pointer ::
value => null()
47 logical :: destroy_on_delete
48 type(node),
pointer :: next => null()
49 type(node),
pointer :: previous => null()
51 procedure,
public :: init => node_init
52 procedure,
public :: final => node_final
53 procedure,
public :: getdata => node_get_data
58 type(node),
pointer,
private :: head
59 type(node),
pointer,
private :: tail
60 integer,
private :: counter
62 procedure,
public :: init => linkedlist_init
63 procedure,
public :: final => linkedlist_final
64 procedure,
public :: addbypointer => linkedlist_add_by_pointer
65 procedure,
public :: removebypointer => linkedlist_remove_by_pointer
66 procedure,
public :: remove => linkedlist_remove_by_key
67 procedure,
public :: addbyclone => linkedlist_add_by_clone
68 procedure,
public :: getnode => linkedlist_get_node
69 procedure,
public :: get => linkedlist_get_data
70 procedure,
public :: traverselist => linkedlist_traverse_list
71 procedure,
public :: traverse => linkedlist_traverse
73 procedure,
private :: keysequal => linkedlist_keys_eqaul
91 type(node),
pointer :: this
92 logical,
intent(out) :: done
95 subroutine key_iterator(key, value, done)
97 class(*),
intent(in) :: key
98 class(*),
pointer :: value
99 logical,
intent(out) :: done
100 end subroutine key_iterator
104 subroutine node_init( this, key, value, previous_node, destroy_on_delete )
107 class(*),
intent(in) :: key
108 class(*),
pointer,
intent(in) :: value
109 type(node),
pointer :: previous_node
110 logical,
intent(in) :: destroy_on_delete
113 allocate( this%key, source=key )
115 this%previous => previous_node
116 this%destroy_on_delete = destroy_on_delete
119 end subroutine node_init
121 subroutine node_final( this )
123 class(node),
intent(inout) :: this
126 if(
allocated( this%key ) )
deallocate( this%key )
127 if ( this%destroy_on_delete )
then
128 if (
associated( this%value) )
deallocate( this%value )
132 end subroutine node_final
134 subroutine node_get_data( this, value )
137 class(*),
pointer,
intent(out) :: value
140 if (
associated(this%value) )
then
143 log_error(
" Node_get_data",*)
"The pointer into data of node is not associated. Check!"
147 end subroutine node_get_data
151 subroutine linkedlist_init( this )
157 nullify( this%head, this%tail )
160 end subroutine linkedlist_init
162 subroutine linkedlist_final( this )
168 if (
associated(this%head) )
call destroy_subsequent_nodes( this%head )
171 end subroutine linkedlist_final
173 recursive subroutine destroy_subsequent_nodes( this_node )
175 type(node),
pointer,
intent(inout) :: this_node
178 if (
associated(this_node) )
then
179 call this_node%Final()
180 call destroy_subsequent_nodes( this_node%next )
181 nullify( this_node%previous )
182 deallocate( this_node )
187 end subroutine destroy_subsequent_nodes
190 function linkedlist_has_key( this, key )
result(has_key)
193 class(*),
intent(in) :: key
198 call this%TraverseList( key_search )
201 subroutine key_search(ptr, done)
203 type(node),
pointer :: ptr
204 logical,
intent(out) :: done
206 has_key = this%keysEqual(ptr%key, key)
209 end subroutine key_search
210 end function linkedlist_has_key
212 subroutine linkedlist_traverse_list( &
219 type(node),
pointer :: ptr
227 if (
associated(ptr))
then
228 call iterator( ptr, done )
237 end subroutine linkedlist_traverse_list
239 subroutine linkedlist_traverse( &
244 procedure(key_iterator) :: iterator
248 call this%TraverseList( key_iterator_wrapper )
252 subroutine key_iterator_wrapper( this_node, done )
254 type(node),
pointer :: this_node
255 logical,
intent(out) :: done
258 call iterator( this_node%key, this_node%value, done )
260 end subroutine key_iterator_wrapper
262 end subroutine linkedlist_traverse
264 subroutine linkedlist_add_by_pointer( &
265 this, key, value, destroy_on_delete )
269 class(*),
intent(in) :: key
270 class(*),
pointer,
intent(in) :: value
271 logical,
intent(in),
optional :: destroy_on_delete
273 type(node),
pointer :: pNode
274 logical :: destroy_on_delete_ = .false.
279 type is (
character(len=*))
282 log_error(
"LinkedList_add_by_pointer",*)
"The type of key is invalid. Check!"
285 call this%GetNode( key, pnode )
286 if (
associated(pnode) )
call this%RemoveByPointer( pnode )
289 if (
present(destroy_on_delete))
then
290 destroy_on_delete_ = destroy_on_delete
292 call pnode%Init( key,
value, this%tail, destroy_on_delete_ )
294 if (
associated(this%tail) )
then
295 this%tail%next => pnode
300 this%counter = this%counter + 1
303 end subroutine linkedlist_add_by_pointer
305 subroutine linkedlist_add_by_clone( this, key, value )
308 class(*),
intent(in) :: key
309 class(*),
intent(in) :: value
311 class(*),
pointer :: ptr_value
314 allocate(ptr_value, source=
value)
315 call this%AddByPointer( key, ptr_value, destroy_on_delete=.true. )
318 end subroutine linkedlist_add_by_clone
320 subroutine linkedlist_remove_by_key( this, key )
323 class(*),
intent(in) :: key
325 type(node),
pointer :: pNode
328 call this%GetNode( key, pnode )
329 call this%RemoveByPointer( pnode )
332 end subroutine linkedlist_remove_by_key
334 subroutine linkedlist_remove_by_pointer( this, pNode )
337 type(node),
pointer :: pNode
340 logical :: has_previous
343 if (
associated(pnode) )
then
344 has_next =
associated( pnode%next )
345 has_previous =
associated( pnode%previous )
347 if ( has_next .and. has_previous )
then
348 pnode%previous%next => pnode%next
349 pnode%next%previous => pnode%previous
350 else if ( has_next .and. .not. has_previous )
then
351 this%head => pnode%next
352 nullify( this%head%previous )
353 else if ( .not. has_next .and. has_previous )
then
354 this%tail => pnode%previous
355 nullify( this%tail%next )
356 else if ( .not. (has_next .or. has_previous) )
then
357 nullify( this%head, this%tail )
364 this%counter = this%counter - 1
368 end subroutine linkedlist_remove_by_pointer
370 subroutine linkedlist_get_node( this, key, ptr_node )
373 class(*),
intent(in) :: key
374 type(node),
pointer,
intent(out) :: ptr_node
376 type(node),
pointer :: ptr
383 if (
associated(ptr) )
then
384 if (this%keysEqual(ptr%key, key))
then
394 end subroutine linkedlist_get_node
396 subroutine linkedlist_get_data( this, key, ptr_value )
399 class(*),
intent(in) :: key
400 class(*),
pointer,
intent(out) :: ptr_value
402 type(node),
pointer :: ptr
405 call this%GetNode( key, ptr )
406 if (
associated(ptr) )
then
407 ptr_value => ptr%value
413 end subroutine linkedlist_get_data
415 function linkedlist_keys_eqaul( this, key1, key2 )
result(is_keys_eqaul)
418 class(*),
intent(in) :: key1
419 class(*),
intent(in) :: key2
420 logical :: is_keys_eqaul
424 is_keys_eqaul = .false.
426 if ( same_type_as(key1, key2) )
then
431 is_keys_eqaul = (key1 == key2)
433 type is (
character(len=*))
435 type is (
character(len=*))
436 is_keys_eqaul = (key1 == key2)
447 end function linkedlist_keys_eqaul
449end module scale_linkedlist
module common / data collection