• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

trixi-framework / FTObjectLibrary / 30206241592

26 Jul 2026 02:31PM UTC coverage: 92.391% (-2.2%) from 94.58%
30206241592

Pull #79

github

web-flow
Merge 79dc9ef6b into 58212d52c
Pull Request #79: Type mods2

89 of 126 new or added lines in 17 files covered. (70.63%)

33 existing lines in 4 files now uncovered.

2732 of 2957 relevant lines covered (92.39%)

14.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.33
/Source/FTObjects/FTLinkedListClass.f90
1
! MIT License
2
!
3
! Copyright (c) 2010-present David A. Kopriva and other contributors: AUTHORS.md
4
!
5
! Permission is hereby granted, free of charge, to any person obtaining a copy  
6
! of this software and associated documentation files (the "Software"), to deal  
7
! in the Software without restriction, including without limitation the rights  
8
! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
9
! copies of the Software, and to permit persons to whom the Software is  
10
! furnished to do so, subject to the following conditions:
11
!
12
! The above copyright notice and this permission notice shall be included in all  
13
! copies or substantial portions of the Software.
14
!
15
! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
16
! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
17
! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
18
! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
19
! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
20
! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  
21
! SOFTWARE.
22
!
23
! FTObjectLibrary contains code that, to the best of our knowledge, has been released as
24
! public domain software:
25
! * `b3hs_hash_key_jenkins`: originally by Rich Townsend, 
26
! https://groups.google.com/forum/#!topic/comp.lang.fortran/RWoHZFt39ng, 2005
27
!
28
! --- End License
29

30
!
31
!////////////////////////////////////////////////////////////////////////
32
!
33
!      FTLinkedListClass.f90
34
!      Created: January 7, 2013 2:56 PM 
35
!      By: David Kopriva  
36
!
37
!
38
!
39
!////////////////////////////////////////////////////////////////////////
40
!
41
!@mark -
42
!
43
!>FTLinkedListRecord is the record type (object and next) for the
44
!>LinkedList class.
45
!>
46
!>One will generally not instantiate a record oneself. They are 
47
!>created automatically when one adds an object to a linked list.
48
!>
49
      Module FTLinkedListRecordClass 
50
      USE FTObjectClass
51
      IMPLICIT NONE 
52
!
53
!     -----------------------------
54
!     Record class for linked lists
55
!     -----------------------------
56
!
57
      TYPE, EXTENDS(FTObject) :: FTLinkedListRecord
58
      
59
         CLASS(FTObject)          , POINTER :: recordObject => NULL()
60
         CLASS(FTLinkedListRecord), POINTER :: next => NULL(), previous => NULL()
61
!
62
!        ========         
63
         CONTAINS
64
!        ========
65
!
66
         PROCEDURE :: initWithObject
67
         FINAL     :: destructFTLinkedListRecord
68
         PROCEDURE :: printDescription => printFTLinkedRecordDescription
69
         PROCEDURE :: className        => llRecordClassName
70
         
71
      END TYPE FTLinkedListRecord
72
!
73
!     ----------
74
!     Procedures
75
!     ----------
76
!
77
      CONTAINS 
78
!
79
!////////////////////////////////////////////////////////////////////////
80
!
81
      SUBROUTINE initWithObject(self,obj) 
102✔
82
         IMPLICIT NONE 
83
         CLASS(FTLinkedListRecord) :: self
84
         CLASS(FTObject), POINTER  :: obj
85
!
86
!        -------------------------------
87
!        Always call the superclass init
88
!        -------------------------------
89
!
90
         CALL self % FTObject % init()
102✔
91
!
92
!        ------------------------
93
!        Subclass initializations
94
!        ------------------------
95
!
96
         CALL obj % retain()
102✔
97
         
98
         self % recordObject => obj
102✔
99
         self % next         => NULL()
102✔
100
         self % previous     => NULL()
102✔
101
         
102
      END SUBROUTINE initWithObject
102✔
103
!
104
!////////////////////////////////////////////////////////////////////////
105
!
106
!< The destructor must only be called from within subclass destructors
107
!
108
      SUBROUTINE destructFTLinkedListRecord(self) 
49✔
109
         IMPLICIT NONE
110
         TYPE(FTLinkedListRecord) :: self
111
         
112
         IF ( ASSOCIATED(self % recordObject) ) CALL releaseFTObject(self % recordObject)
49✔
113
         self % next     => NULL()
49✔
114
         self % previous => NULL()
49✔
115
        
116
      END SUBROUTINE destructFTLinkedListRecord
49✔
117
!
118
!//////////////////////////////////////////////////////////////////////// 
119
! 
120
      SUBROUTINE releaseFTLinkedListRecord(self)  
×
121
         IMPLICIT NONE
122
         TYPE(FTLinkedListRecord), POINTER :: self
123
         CLASS(FTObject)         , POINTER :: obj
124
         
125
         IF(.NOT. ASSOCIATED(self)) RETURN
×
126
         
127
         obj => self
×
128
         CALL release(obj) 
×
129
         IF(.NOT.ASSOCIATED(obj)) self => NULL()
×
130
      END SUBROUTINE releaseFTLinkedListRecord
131
!
132
!//////////////////////////////////////////////////////////////////////// 
133
! 
134
      RECURSIVE SUBROUTINE printFTLinkedRecordDescription(self,iUnit)  
2✔
135
         IMPLICIT NONE  
136
         CLASS(FTLinkedListRecord) :: self
137
         INTEGER                   :: iUnit
138

139
         IF ( ASSOCIATED(self % recordObject) )     THEN
2✔
140
            CALL self % recordObject % printDescription(iUnit)
2✔
141
         END IF 
142
         
143
      END SUBROUTINE printFTLinkedRecordDescription
2✔
144
!
145
!//////////////////////////////////////////////////////////////////////// 
146
! 
147
!      -----------------------------------------------------------------
148
!> Class name returns a string with the name of the type of the object
149
!>
150
!>  ### Usage:
151
!>
152
!>        PRINT *,  obj % className()
153
!>        if( obj % className = "FTLinkedListRecord")
154
!>
155
      FUNCTION llRecordClassName(self)  RESULT(s)
×
156
         IMPLICIT NONE  
157
         CLASS(FTLinkedListRecord)                  :: self
158
         CHARACTER(LEN=CLASS_NAME_CHARACTER_LENGTH) :: s
159
         
160
         s = "FTLinkedListRecord"
×
161
 
162
      END FUNCTION llRecordClassName
×
163

164
      
165
      END MODULE FTLinkedListRecordClass  
151✔
166
!@mark -
167
!
168
!
169
!     --------------------------------------------------
170
!     Implements the basics of a linked list of objects
171
!     --------------------------------------------------
172
!
173
!>
174
!>FTLinkedList is a container class that stores objects in a linked list.
175
!>
176
!>Inherits from FTObjectClass
177
!>
178
!>##Definition (Subclass of FTObject):
179
!>
180
!>         TYPE(FTLinkedList) :: list
181
!>
182
!>#Usage:
183
!>
184
!>##Initialization
185
!>
186
!>         CLASS(FTLinkedList), POINTER :: list
187
!>         ALLOCATE(list)
188
!>         CALL list % init
189
!>
190
!>##Adding objects
191
!>
192
!>         CLASS(FTLinkedList), POINTER :: list, listToAdd
193
!>         CLASS(FTObject)    , POINTER :: objectPtr
194
!>
195
!>         objectPtr => r                ! r is subclass of FTObject
196
!>         CALL list % Add(objectPtr)    ! Pointer is retained by list
197
!>         CALL release(r)               ! If caller relinquishes ownership
198
!>
199
!>         CALL list % addObjectsFromList(listToAdd)
200
!>
201
!>##Inserting objects
202
!>
203
!>         CLASS(FTLinkedList)      , POINTER :: list
204
!>         CLASS(FTObject)          , POINTER :: objectPtr, obj
205
!>         CLASS(FTLinkedListRecord), POINTER :: record
206
!>
207
!>         objectPtr => r                                        ! r is subclass of FTObject
208
!>         CALL list % insertObjectAfterRecord(objectPtr,record) ! Pointer is retained by list
209
!>         CALL release(r)                                       ! If caller reliquishes ownership
210
!>
211
!>         objectPtr => r                                     ! r is subclass of FTObject
212
!>         CALL list % insertObjectAfterObject(objectPtr,obj) ! Pointer is retained by list
213
!>         CALL release(r)                                    ! If caller reliquishes ownership
214
!>
215
!>##Removing objects
216
!>
217
!>         CLASS(FTLinkedList), POINTER :: list
218
!>         CLASS(FTObject)    , POINTER :: objectPtr
219
!>         objectPtr => r                 ! r is subclass of FTObject
220
!>         CALL list % remove(objectPtr)
221
!>
222
!>##Getting all objects as an object array
223
!>
224
!>         CLASS(FTLinkedList)        , POINTER :: list
225
!>         CLASS(FTMutableObjectArray), POINTER :: array
226
!>         array => list % allObjects() ! Array has refCount = 1
227
!>
228
!>##Counting the number of objects in the list
229
!>
230
!>         n = list % count()
231
!>
232
!>##Destruction
233
!>   
234
!>         CALL releaseFTLinkedList(list) [Pointers]
235
!>!
236
      Module FTLinkedListClass
237
!      
238
      USE FTLinkedListRecordClass
239
      USE FTMutableObjectArrayClass
240
      IMPLICIT NONE 
241
!
242
!     -----------------
243
!     Class object type
244
!     -----------------
245
!
246
      TYPE, EXTENDS(FTObject) :: FTLinkedList
247
      
248
         CLASS(FTLinkedListRecord), POINTER :: head => NULL(), tail => NULL()
249
         INTEGER                            :: nRecords
250
         LOGICAL                            :: isCircular_
251
!
252
!        ========         
253
         CONTAINS
254
!        ========
255
!
256
         PROCEDURE :: init             => initFTLinkedList
257
         PROCEDURE :: add              
258
         PROCEDURE :: remove           => removeObject
259
         PROCEDURE :: reverse          => reverseLinkedList
260
         PROCEDURE :: removeRecord     => removeLinkedListRecord
261
         FINAL     :: destructFTLinkedList
262
         PROCEDURE :: count            => numberOfRecords
263
         PROCEDURE :: description      => FTLinkedListDescription
264
         PROCEDURE :: printDescription => printFTLinkedListDescription
265
         PROCEDURE :: className        => linkedListClassName
266
         PROCEDURE :: allObjects       => allLinkedListObjects
267
         PROCEDURE :: removeAllObjects => removeAllLinkedListObjects
268
         PROCEDURE :: addObjectsFromList
269
         PROCEDURE :: makeCircular
270
         PROCEDURE :: isCircular
271
         PROCEDURE :: insertObjectAfterRecord
272
         PROCEDURE :: insertObjectAfterObject
273
         
274
      END TYPE FTLinkedList
275
      
276
      INTERFACE cast
277
         MODULE PROCEDURE castObjectToLinkedList
278
      END INTERFACE cast
279
!
280
!     ----------
281
!     Procedures
282
!     ----------
283
!
284
      CONTAINS 
285
!
286
!////////////////////////////////////////////////////////////////////////
287
!
288
      SUBROUTINE initFTLinkedList(self) 
385✔
289
         IMPLICIT NONE 
290
         CLASS(FTLinkedList) :: self
291
!
292
!        -------------------------------
293
!        Always call the superclass init
294
!        -------------------------------
295
!
296
         CALL self % FTObject % init()
385✔
297
!
298
!        --------------------------------------
299
!        Then call the subclass initializations
300
!        --------------------------------------
301
!
302
         self % nRecords    = 0
385✔
303
         self % isCircular_ = .FALSE.
385✔
304
         
305
         self % head => NULL(); self % tail => NULL()
385✔
306
         
307
      END SUBROUTINE initFTLinkedList
385✔
308
!
309
!////////////////////////////////////////////////////////////////////////
310
!
311
      SUBROUTINE add(self,obj)
94✔
312
         IMPLICIT NONE 
313
         CLASS(FTLinkedList)                :: self
314
         CLASS(FTObject)          , POINTER :: obj
315
         CLASS(FTLinkedListRecord), POINTER :: newRecord => NULL()
316
         
317
         ALLOCATE(newRecord)
94✔
318
         CALL newRecord % initWithObject(obj)
94✔
319
         
320
         IF ( .NOT.ASSOCIATED(self % head) )     THEN
94✔
321
            self % head => newRecord
60✔
322
         ELSE
323
            self % tail % next   => newRecord
34✔
324
            newRecord % previous => self % tail
34✔
325
         END IF
326
         
327
         self % tail => newRecord
94✔
328
         self % nRecords = self % nRecords + 1
94✔
329
         
330
      END SUBROUTINE add 
94✔
331
!
332
!////////////////////////////////////////////////////////////////////////
333
!
334
      SUBROUTINE addObjectsFromList(self,list)
1✔
335
         IMPLICIT NONE 
336
         CLASS(FTLinkedList)                :: self
337
         CLASS(FTLinkedList)      , POINTER :: list
338
         CLASS(FTLinkedListRecord), POINTER :: recordPtr => NULL()
339
         CLASS(FtObject)          , POINTER :: obj       => NULL()
340
         LOGICAL                            :: circular
341
         
342
         IF(.NOT.ASSOCIATED(list % head)) RETURN
1✔
343
         
344
         circular = list % isCircular()
1✔
345
         CALL list % makeCircular(.FALSE.)
1✔
346

347
         recordPtr => list % head
1✔
348
         DO WHILE(ASSOCIATED( recordPtr ))
6✔
349
            obj => recordPtr % recordObject
5✔
350
            CALL self % add(obj)
5✔
351
            
352
            recordPtr => recordPtr % next
5✔
353
         END DO
354
         
355
         CALL list % makeCircular(circular) 
1✔
356
         
357
      END SUBROUTINE addObjectsFromList 
358
!
359
!////////////////////////////////////////////////////////////////////////
360
!
361
      SUBROUTINE insertObjectAfterRecord(self,obj,after)
1✔
362
         IMPLICIT NONE 
363
         CLASS(FTLinkedList)                :: self
364
         CLASS(FTObject)          , POINTER :: obj
365
         CLASS(FTLinkedListRecord), POINTER :: newRecord   => NULL()
366
         CLASS(FTLinkedListRecord), POINTER :: after, next => NULL()
367
         
368
         ALLOCATE(newRecord)
1✔
369
         CALL newRecord % initWithObject(obj)
1✔
370
         
371
         next                 => after % next
1✔
372
         newRecord % next     => next
1✔
373
         newRecord % previous => after
1✔
374
         after % next         => newRecord
1✔
375
         next % previous      => newRecord
1✔
376
         
377
         IF ( .NOT.ASSOCIATED( newRecord % next ) )     THEN
1✔
378
            self % tail => newRecord 
×
379
         END IF 
380
         
381
         self % nRecords = self % nRecords + 1
1✔
382
         
383
      END SUBROUTINE insertObjectAfterRecord 
1✔
384
!
385
!////////////////////////////////////////////////////////////////////////
386
!
387
      SUBROUTINE insertObjectAfterObject(self,obj,after)
1✔
388
         IMPLICIT NONE 
389
         CLASS(FTLinkedList)                :: self
390
         CLASS(FTObject)          , POINTER :: obj, after
391
         
392
         CLASS(FTLinkedListRecord), POINTER :: current => NULL(), previous => NULL()
393
                  
394
         IF ( .NOT.ASSOCIATED(self % head) )     THEN
1✔
395
            CALL self % add(obj)
×
396
            RETURN 
×
397
         END IF 
398
         
399
         current  => self % head
1✔
400
         previous => NULL()
1✔
401
!
402
!        -------------------------------------------------------------
403
!        Find the object in the list by a linear search and 
404
!        add the new object after it.
405
!        It will be deallocated if necessary.
406
!        -------------------------------------------------------------
407
!
408
         DO WHILE (ASSOCIATED(current))
3✔
409
         
410
            IF ( ASSOCIATED(current % recordObject,after) )     THEN
3✔
411
               CALL self % insertObjectAfterRecord(obj = obj,after = current)
1✔
412
               RETURN 
1✔
413
            END IF 
414
            
415
            previous => current
2✔
416
            current  => current % next
2✔
417
         END DO
418
         
419
      END SUBROUTINE insertObjectAfterObject 
420
!
421
!//////////////////////////////////////////////////////////////////////// 
422
! 
423
      SUBROUTINE makeCircular(self,circular)  
21✔
424
         IMPLICIT NONE  
425
         CLASS(FTLinkedList) :: self
426
         LOGICAL             :: circular
427
         
428
         IF ( circular )     THEN
21✔
429
            self % head % previous => self % tail
×
430
            self % tail % next     => self % head
×
431
            self % isCircular_ = .TRUE.
×
432
         ELSE
433
            self % head % previous => NULL()
21✔
434
            self % tail % next     => NULL()
21✔
435
            self % isCircular_ = .FALSE.
21✔
436
         END IF 
437
      END SUBROUTINE makeCircular
21✔
438
!
439
!//////////////////////////////////////////////////////////////////////// 
440
! 
441
      LOGICAL FUNCTION isCircular(self)  
18✔
442
         IMPLICIT NONE  
443
         CLASS(FTLinkedList) :: self
444
         isCircular = self % isCircular_
18✔
445
      END FUNCTION isCircular
18✔
446
!
447
!////////////////////////////////////////////////////////////////////////
448
!
449
      SUBROUTINE removeObject(self,obj)
2✔
450
         IMPLICIT NONE 
451
         CLASS(FTLinkedList)                :: self
452
         CLASS(FTObject)          , POINTER :: obj
453
         
454
         CLASS(FTLinkedListRecord), POINTER :: current => NULL(), previous => NULL()
455
                  
456
         IF ( .NOT.ASSOCIATED(self % head) )     RETURN
2✔
457
         
458
         current  => self % head
2✔
459
         previous => NULL()
2✔
460
!
461
!        -------------------------------------------------------------
462
!        Find the object in the list by a linear search and remove it.
463
!        It will be deallocated if necessary.
464
!        -------------------------------------------------------------
465
!
466
         DO WHILE (ASSOCIATED(current))
3✔
467
         
468
            IF ( ASSOCIATED(current % recordObject,obj) )     THEN
3✔
469
               CALL self % removeRecord(current)
2✔
470
               EXIT
2✔
471
            END IF 
472
            
473
            previous => current
1✔
474
            current  => current % next
1✔
475
         END DO
476
         
477
      END SUBROUTINE removeObject 
478
!
479
!////////////////////////////////////////////////////////////////////////
480
!
481
      SUBROUTINE removeLinkedListRecord(self,listRecord)
5✔
482
         IMPLICIT NONE 
483
!
484
!        ---------
485
!        Arguments
486
!        ---------
487
!
488
         CLASS(FTLinkedList)                :: self
489
         CLASS(FTLinkedListRecord), POINTER :: listRecord
490
!
491
!        ---------------
492
!        Local variables
493
!        ---------------
494
!
495
         CLASS(FTLinkedListRecord), POINTER :: previous => NULL(), next => NULL()
496
         CLASS(FTObject)          , POINTER :: obj
497
!
498
!        ---------------------------------------------------
499
!        Turn cirularity off and then back on
500
!        to work around an what appears to be an
501
!        ifort bug testing the association of two pointers. 
502
!        ---------------------------------------------------
503
!
504
         LOGICAL :: circ
505
         circ = self % isCircular()
5✔
506
         IF(circ) CALL self % makeCircular(.FALSE.)
5✔
507
         
508
         previous => listRecord % previous
5✔
509
         next     => listRecord % next
5✔
510
         
511
         IF ( .NOT.ASSOCIATED(listRecord % previous) )     THEN
5✔
512
            self % head => next
2✔
513
            IF ( ASSOCIATED(next) )     THEN
2✔
514
               self % head % previous => NULL() 
2✔
515
            END IF  
516
         END IF 
517
         
518
         IF ( .NOT.ASSOCIATED(listRecord % next) )     THEN
5✔
519
            self % tail => previous
1✔
520
            IF ( ASSOCIATED(previous) )     THEN
1✔
521
               self % tail % next => NULL() 
1✔
522
            END IF
523
         END IF 
524
         
525
         IF ( ASSOCIATED(previous) .AND. ASSOCIATED(next) )     THEN
5✔
526
            previous % next => next
2✔
527
            next % previous => previous 
2✔
528
         END IF 
529
         
530
         obj => listRecord
5✔
531
         CALL release(obj)
5✔
532
         
533
         self % nRecords = self % nRecords - 1
5✔
534
         IF(circ) CALL self % makeCircular(.TRUE.)
5✔
535
         
536
      END SUBROUTINE removeLinkedListRecord
5✔
537
!
538
!//////////////////////////////////////////////////////////////////////// 
539
! 
540
      SUBROUTINE removeAllLinkedListObjects(self)  
15✔
541
         IMPLICIT NONE
542
         CLASS(FTLinkedList)                :: self
543
         CLASS(FTLinkedListRecord), POINTER :: listRecord => NULL(), tmp => NULL()
544
         LOGICAL                            :: circular
545
         CLASS(FTObject)          , POINTER :: obj
546

547
         IF(.NOT.ASSOCIATED(self % head)) RETURN 
15✔
548
         
549
         circular = self % isCircular()
12✔
550
         CALL self % makeCircular(.FALSE.)
12✔
551
         
552
         listRecord => self % head
12✔
553
         DO WHILE (ASSOCIATED(listRecord))
54✔
554

555
            tmp => listRecord % next
42✔
556

557
            obj => listRecord
42✔
558
            CALL release(obj)
42✔
559

560
            IF(.NOT. ASSOCIATED(listRecord)) THEN
42✔
561
               self % nRecords = self % nRecords - 1
×
562
            END IF
563
            listRecord => tmp
42✔
564
         END DO
565

566
         self % head => NULL(); self % tail => NULL()
12✔
567
         
568
      END SUBROUTINE removeAllLinkedListObjects
569
!
570
!//////////////////////////////////////////////////////////////////////// 
571
! 
572
      INTEGER FUNCTION numberOfRecords(self)  
195✔
573
         IMPLICIT NONE  
574
         CLASS(FTLinkedList) :: self
575
          numberOfRecords = self % nRecords
195✔
576
      END FUNCTION numberOfRecords     
195✔
577
!
578
!//////////////////////////////////////////////////////////////////////// 
579
! 
580
      SUBROUTINE releaseFTLinkedListClass(self)  
6✔
581
         IMPLICIT NONE
582
         CLASS (FTLinkedList), POINTER :: self
583
         CLASS(FTObject)   , POINTER :: obj
584
          
585
         IF(.NOT. ASSOCIATED(self)) RETURN
6✔
586
        
587
         obj => self
6✔
588
         CALL release(obj) 
6✔
589
         IF(.NOT.ASSOCIATED(obj)) self => NULL()
6✔
590
      END SUBROUTINE releaseFTLinkedListClass
591
!
592
!//////////////////////////////////////////////////////////////////////// 
593
! 
NEW
594
      SUBROUTINE releaseFTLinkedList(self)  
×
595
         IMPLICIT NONE
596
         TYPE (FTLinkedList), POINTER :: self
597
         CLASS(FTObject)   , POINTER :: obj
598
          
NEW
599
         IF(.NOT. ASSOCIATED(self)) RETURN
×
600
        
UNCOV
601
         obj => self
×
UNCOV
602
         CALL release(obj) 
×
UNCOV
603
         IF(.NOT.ASSOCIATED(obj)) self => NULL()
×
604
      END SUBROUTINE releaseFTLinkedList
605
!
606
!////////////////////////////////////////////////////////////////////////
607
!
608
!< The destructor must only be called from within the destructors of subclasses
609
!> It is automatically called by release().
610
!
611
      SUBROUTINE destructFTLinkedList(self) 
15✔
612
         IMPLICIT NONE
613
         TYPE(FTLinkedList)                :: self
614

615
         CALL self % removeAllObjects()
15✔
616

617
      END SUBROUTINE destructFTLinkedList
15✔
618
!
619
!//////////////////////////////////////////////////////////////////////// 
620
! 
621
      FUNCTION FTLinkedListDescription(self)  
16✔
622
         IMPLICIT NONE  
623
         CLASS(FTLinkedList)                         :: self
624
         CLASS(FTLinkedListRecord), POINTER          :: listRecord => NULL()
625
         CHARACTER(LEN=DESCRIPTION_CHARACTER_LENGTH) :: FTLinkedListDescription
626
         
627
         
628
         FTLinkedListDescription = ""
16✔
629
         IF(.NOT.ASSOCIATED(self % head)) RETURN
16✔
630
         
631
         listRecord              => self % head
1✔
632
         FTLinkedListDescription = TRIM(listRecord % recordObject % description())
1✔
633
         listRecord              => listRecord % next
1✔
634

635
         DO WHILE (ASSOCIATED(listRecord))
1✔
636
            FTLinkedListDescription = TRIM(FTLinkedListDescription) // &
637
                                       CHAR(13) // &
638
                                       TRIM(listRecord % recordObject % description())
×
639
            listRecord => listRecord % next
×
640
         END DO
641
      END FUNCTION FTLinkedListDescription    
642
!
643
!//////////////////////////////////////////////////////////////////////// 
644
! 
645
      RECURSIVE SUBROUTINE printFTLinkedListDescription(self,iUnit)  
72✔
646
         IMPLICIT NONE  
647
         CLASS(FTLinkedList)                 :: self
648
         INTEGER                             :: iUnit
649
         CLASS(FTLinkedListRecord), POINTER  :: listRecord => NULL()
650
         LOGICAL                             :: circular
651
         
652
         IF(.NOT.ASSOCIATED(self % head)) RETURN
72✔
653
         
654
         circular                        = .FALSE.
2✔
655
         IF(self % isCircular_) circular = .TRUE.
2✔
656
         CALL self % makeCircular(.FALSE.)
2✔
657
         
658
         listRecord => self % head
2✔
659

660
         DO WHILE (ASSOCIATED(listRecord)) 
4✔
661
            CALL listRecord % printDescription(iUnit)
2✔
662
            IF(.NOT. ASSOCIATED(listRecord)) EXIT !TODO Don't understand why this is necessary. Why is record being unassociated?
2✔
663
            listRecord => listRecord % next
2✔
664
         END DO
665
         
666
         CALL self % makeCircular (circular)
2✔
667
         
668
      END SUBROUTINE printFTLinkedListDescription
669
!
670
!//////////////////////////////////////////////////////////////////////// 
671
! 
672
      SUBROUTINE reverseLinkedList(self)
1✔
673
!
674
!     ------------------------
675
!     Reverses the linked list
676
!     ------------------------
677
!
678
         IMPLICIT NONE 
679
!
680
!        ---------
681
!        Arguments
682
!        ---------
683
!
684
         CLASS(FTLinkedList) :: self
685
!
686
!        ---------------
687
!        Local variables
688
!        ---------------
689
!
690
         CLASS(FTLinkedListRecord), POINTER :: current => NULL(), tmp => NULL()
691
         
692
         IF(.NOT.ASSOCIATED(self % head)) RETURN
1✔
693
         
694
         IF ( self % isCircular_ )     THEN
1✔
695
            self % head % previous => NULL()
×
696
            self % tail % next     => NULL() 
×
697
         END IF
698
         
699
         current  => self % head
1✔
700

701
         DO WHILE (ASSOCIATED(current))
11✔
702
            tmp                => current % next
10✔
703
            current % next     => current % previous
10✔
704
            current % previous => tmp
10✔
705
            current            => tmp
10✔
706
         END DO
707
         
708
         tmp => self % head
1✔
709
         self % head => self % tail
1✔
710
         self % tail => tmp
1✔
711
         
712
         CALL self % makeCircular(self % isCircular_) 
1✔
713
         
714
      END SUBROUTINE reverseLinkedList
715
!
716
!//////////////////////////////////////////////////////////////////////// 
717
! 
718
      FUNCTION allLinkedListObjects(self)  RESULT(array)
1✔
719
         IMPLICIT NONE  
720
!
721
!        ---------
722
!        Arguments
723
!        ---------
724
!
725
         CLASS (FTLinkedList)                 :: self
726
         CLASS(FTMutableObjectArray), POINTER :: array
727
!
728
!        ---------------
729
!        Local variables
730
!        ---------------
731
!
732
         INTEGER                            :: N
733
         CLASS(FTLinkedListRecord), POINTER :: listRecord => NULL()
734
         CLASS(FTObject)          , POINTER :: obj        => NULL()
735
         LOGICAL                            :: circular
736
         
737
         array => NULL()
1✔
738
         IF(.NOT.ASSOCIATED(self % head)) RETURN
1✔
739
         
740
         circular                        = .FALSE.
1✔
741
         IF(self % isCircular_) circular = .TRUE.
1✔
742
         CALL self % makeCircular(.FALSE.)
1✔
743
         
744
         array => NULL()
1✔
745
         N = self % count()
1✔
746
         IF(N==0)     RETURN
1✔
747
         
748
         ALLOCATE(array)
1✔
749
         CALL array % initWithSize(arraySize  = N)
1✔
750
         
751
         listRecord => self % head
1✔
752

753
         DO WHILE (ASSOCIATED(listRecord))
11✔
754
            obj => listRecord % recordObject
10✔
755
            CALL array % addObject(obj)
10✔
756
            listRecord => listRecord % next
10✔
757
         END DO
758
         
759
         CALL self % makeCircular(circular)
1✔
760
         
761
      END FUNCTION allLinkedListObjects
1✔
762
!
763
!//////////////////////////////////////////////////////////////////////// 
764
! 
765
!      -----------------------------------------------------------------
766
!> Class name returns a string with the name of the type of the object
767
!>
768
!>  ### Usage:
769
!>
770
!>        PRINT *,  obj % className()
771
!>        if( obj % className = "FTLinkedList")
772
!>
773
      FUNCTION linkedListClassName(self)  RESULT(s)
1✔
774
         IMPLICIT NONE  
775
         CLASS(FTLinkedList)                        :: self
776
         CHARACTER(LEN=CLASS_NAME_CHARACTER_LENGTH) :: s
777
         
778
         s = "FTLinkedList"
1✔
779
 
780
      END FUNCTION linkedListClassName
1✔
781
!@mark -
782
! type conversions
783
!
784
!//////////////////////////////////////////////////////////////////////// 
785
! 
786
      SUBROUTINE castObjectToLinkedList(obj,cast) 
1✔
787
!
788
!     -----------------------------------------------------
789
!     Cast the base class FTObject to the LinkedList class
790
!     -----------------------------------------------------
791
!
792
         IMPLICIT NONE  
793
         CLASS(FTObject)    , POINTER :: obj
794
         CLASS(FTLinkedList), POINTER :: cast
795
         
796
         cast => NULL()
1✔
797
         SELECT TYPE (e => obj)
798
            TYPE is (FTLinkedList)
799
               cast => e
1✔
800
            CLASS DEFAULT
801
               
802
         END SELECT
803
         
804
      END SUBROUTINE castObjectToLinkedList
1✔
805
!
806
!//////////////////////////////////////////////////////////////////////// 
807
! 
808
      FUNCTION linkedListFromObject(obj) RESULT(cast)
1✔
809
!
810
!     -----------------------------------------------------
811
!     Cast the base class FTObject to the LinkedList class
812
!     -----------------------------------------------------
813
!
814
         IMPLICIT NONE  
815
         CLASS(FTObject)    , POINTER :: obj 
816
         CLASS(FTLinkedList), POINTER :: cast
817
         
818
         cast => NULL()
1✔
819
         SELECT TYPE (e => obj)
820
            TYPE is (FTLinkedList)
821
               cast => e
1✔
822
            CLASS DEFAULT
823
               
824
         END SELECT
825
         
826
      END FUNCTION linkedListFromObject
1✔
827
!
828
      END MODULE FTLinkedListClass
70✔
829
!
830
!@mark -
831
!
832
!//////////////////////////////////////////////////////////////////////// 
833
! 
834
!>An object for stepping through a linked list.
835
!>
836
!>###Definition (Subclass of FTObject):
837
!>   TYPE(FTLinkedListIterator) :: list
838
!>
839
!>
840
!>###Initialization
841
!>
842
!>         CLASS(FTLinkedList)        , POINTER :: list
843
!>         CLASS(FTLinkedListIterator), POINTER :: iterator
844
!>         ALLOCATE(iterator)
845
!>         CALL iterator % initWithFTLinkedList(list)
846
!>
847
!>###Accessors
848
!>
849
!>         ptr => iterator % list()
850
!>         ptr => iterator % object()
851
!>         ptr => iterator % currentRecord()
852
!>
853
!>###Iterating
854
!>
855
!>         CLASS(FTObject), POINTER :: objectPtr
856
!>         CALL iterator % setToStart
857
!>         DO WHILE (.NOT.iterator % isAtEnd())
858
!>            objectPtr => iterator % object()        ! if the object is wanted
859
!>            recordPtr => iterator % currentRecord() ! if the record is wanted
860
!>            
861
!>             Do something with object or record
862
!>
863
!>            CALL iterator % moveToNext() ! DON'T FORGET THIS!!
864
!>         END DO
865
!>
866
!>###Destruction
867
!>   
868
!>         CALL releaseFTLinkedListIterator(iterator) [Pointers]
869
!
870
!//////////////////////////////////////////////////////////////////////// 
871
! 
872
      Module FTLinkedListIteratorClass
873
      USE FTLinkedListClass
874
      IMPLICIT NONE
875
!
876
!     -----------------
877
!     Class object type
878
!     -----------------
879
!
880
      TYPE, EXTENDS(FTObject) :: FTLinkedListIterator
881
         CLASS(FTLinkedList)      , POINTER :: list    => NULL()
882
         CLASS(FTLinkedListRecord), POINTER :: current => NULL()
883
!
884
!        ========         
885
         CONTAINS
886
!        ========
887
!
888
         PROCEDURE :: init           => initEmpty
889
         PROCEDURE :: initWithFTLinkedList
890
         PROCEDURE :: initWithFTLinkedListClass
891
         FINAL     :: destructIterator
892
         PROCEDURE :: isAtEnd        => FTLinkedListIsAtEnd
893
         PROCEDURE :: object         => FTLinkedListObject
894
         PROCEDURE :: currentRecord  => FTLinkedListCurrentRecord
895
         PROCEDURE :: linkedList     => returnLinkedList
896
         PROCEDURE :: className      => linkedListIteratorClassName
897
         PROCEDURE :: setLinkedList
898
         PROCEDURE :: setLinkedListClass
899
         PROCEDURE :: setToStart
900
         PROCEDURE :: moveToNext
901
         PROCEDURE :: removeCurrentRecord
902
      END TYPE FTLinkedListIterator
903
!
904
!     ----------
905
!     Procedures
906
!     ----------
907
!
908
      CONTAINS 
909
!
910
!////////////////////////////////////////////////////////////////////////
911
!
912
      SUBROUTINE initEmpty(self) 
2✔
913
         IMPLICIT NONE 
914
         CLASS(FTLinkedListIterator)  :: self
915
!
916
!        --------------------------------------------
917
!        Always call the superclass initializer first
918
!        --------------------------------------------
919
!
920
         CALL self % FTObject % init()
2✔
921
!
922
!        ----------------------------------------------
923
!        Then call the initializations for the subclass
924
!        ----------------------------------------------
925
!
926
         self % list    => NULL()
2✔
927
         self % current => NULL()
2✔
928
         
929
      END SUBROUTINE initEmpty   
2✔
930
!
931
!////////////////////////////////////////////////////////////////////////
932
!
UNCOV
933
      SUBROUTINE initWithFTLinkedList(self,list) 
×
934
         IMPLICIT NONE 
935
         CLASS(FTLinkedListIterator)  :: self
936
         TYPE(FTLinkedList), POINTER  :: list
937
!
938
!        --------------------------------------------
939
!        Always call the superclass initializer first
940
!        --------------------------------------------
941
!
UNCOV
942
         CALL self % FTObject % init()
×
943
!
944
!        ----------------------------------------------
945
!        Then call the initializations for the subclass
946
!        ----------------------------------------------
947
!
UNCOV
948
         self % list    => NULL()
×
UNCOV
949
         self % current => NULL()
×
UNCOV
950
         CALL self % setLinkedList(list)
×
UNCOV
951
         CALL self % setToStart()
×
952
         
UNCOV
953
      END SUBROUTINE initWithFTLinkedList   
×
954
!
955
!////////////////////////////////////////////////////////////////////////
956
!
957
      SUBROUTINE initWithFTLinkedListClass(self,list) 
7✔
958
         IMPLICIT NONE 
959
         CLASS(FTLinkedListIterator)  :: self
960
         CLASS(FTLinkedList), POINTER :: list
961
!
962
!        --------------------------------------------
963
!        Always call the superclass initializer first
964
!        --------------------------------------------
965
!
966
         CALL self % FTObject % init()
7✔
967
!
968
!        ----------------------------------------------
969
!        Then call the initializations for the subclass
970
!        ----------------------------------------------
971
!
972
         self % list    => NULL()
7✔
973
         self % current => NULL()
7✔
974
         CALL self % setLinkedListClass(list)
7✔
975
         CALL self % setToStart()
7✔
976
         
977
      END SUBROUTINE initWithFTLinkedListClass   
7✔
978
!
979
!//////////////////////////////////////////////////////////////////////// 
980
! 
981
      SUBROUTINE releaseFTLinkedListIterator(self)  
4✔
982
         IMPLICIT NONE
983
         TYPE(FTLinkedListIterator), POINTER :: self
984
         CLASS(FTObject)   , POINTER :: obj
985
         
986
         IF(.NOT. ASSOCIATED(self)) RETURN
4✔
987
         
988
         obj => self
4✔
989
         CALL release(obj) 
4✔
990
         IF(.NOT.ASSOCIATED(obj)) self => NULL()
4✔
991
      END SUBROUTINE releaseFTLinkedListIterator
992
!
993
!//////////////////////////////////////////////////////////////////////// 
994
! 
NEW
995
      SUBROUTINE releaseFTLinkedListIteratorClass(self)  
×
996
         IMPLICIT NONE
997
         TYPE(FTLinkedListIterator), POINTER :: self
998
         CLASS(FTObject)   , POINTER :: obj
999
         
NEW
1000
         IF(.NOT. ASSOCIATED(self)) RETURN
×
1001
         
NEW
1002
         obj => self
×
NEW
1003
         CALL release(obj) 
×
NEW
1004
         IF(.NOT.ASSOCIATED(obj)) self => NULL()
×
1005
      END SUBROUTINE releaseFTLinkedListIteratorClass
1006
!
1007
!////////////////////////////////////////////////////////////////////////
1008
!
1009
!< The destructor must not be called except at the end of destructors of
1010
! subclasses.
1011
!
1012
      SUBROUTINE destructIterator(self)
10✔
1013
          IMPLICIT NONE 
1014
          TYPE(FTLinkedListIterator) :: self
1015
          
1016
          CALL releaseMemberList(self)
10✔
1017
          self % current => NULL()
10✔
1018
          
1019
      END SUBROUTINE destructIterator
10✔
1020
!
1021
!//////////////////////////////////////////////////////////////////////// 
1022
! 
1023
      SUBROUTINE releaseMemberList(self)  
23✔
1024
          IMPLICIT NONE  
1025
          CLASS(FTLinkedListIterator) :: self
1026
          CLASS(FTObject), POINTER    :: obj
1027
          
1028
          IF ( ASSOCIATED(self % list) )     THEN
23✔
1029
             obj => self % list
22✔
1030
             CALL releaseFTObject(self = obj)
22✔
1031
             IF(.NOT. ASSOCIATED(obj)) self % list => NULL()
22✔
1032
          END IF 
1033
      END SUBROUTINE releaseMemberList
23✔
1034
!
1035
!////////////////////////////////////////////////////////////////////////
1036
!
1037
      SUBROUTINE setToStart(self) 
68✔
1038
         IMPLICIT NONE 
1039
         CLASS(FTLinkedListIterator)  :: self
1040
         self % current => self % list % head
68✔
1041
      END SUBROUTINE setToStart 
68✔
1042
!
1043
!////////////////////////////////////////////////////////////////////////
1044
!
1045
      SUBROUTINE moveToNext(self) 
79✔
1046
         IMPLICIT NONE 
1047
         CLASS(FTLinkedListIterator)  :: self
1048
         
1049
         IF ( ASSOCIATED(self % current) )     THEN
79✔
1050
            self % current => self % current % next
78✔
1051
         ELSE 
1052
            self % current => NULL() 
1✔
1053
         END IF 
1054
         
1055
         IF ( ASSOCIATED(self % current, self % list % head) )     THEN
79✔
1056
            self % current => NULL() 
×
1057
         END IF 
1058
         
1059
      END SUBROUTINE moveToNext 
79✔
1060
!
1061
!////////////////////////////////////////////////////////////////////////
1062
!
1063
      LOGICAL FUNCTION FTLinkedListIsAtEnd(self)
116✔
1064
         IMPLICIT NONE 
1065
         CLASS(FTLinkedListIterator)  :: self
1066
         IF ( ASSOCIATED(self % current) )     THEN
116✔
1067
            FTLinkedListIsAtEnd = .false.
102✔
1068
         ELSE
1069
            FTLinkedListIsAtEnd = .true.
14✔
1070
         END IF
1071
      END FUNCTION FTLinkedListIsAtEnd   
116✔
1072
!
1073
!////////////////////////////////////////////////////////////////////////
1074
!
1075
      SUBROUTINE setLinkedListClass(self,list)
37✔
1076
         IMPLICIT NONE 
1077
         CLASS(FTLinkedListIterator)  :: self
1078
         CLASS(FTLinkedList), POINTER :: list
1079
!
1080
!        -----------------------------------
1081
!        Remove current list if there is one
1082
!        -----------------------------------
1083
!
1084
         IF ( ASSOCIATED(list) )     THEN
37✔
1085
         
1086
            IF ( ASSOCIATED(self % list, list) )     THEN
37✔
1087
               CALL self % setToStart()
15✔
1088
            ELSE IF( ASSOCIATED(self % list) )     THEN
22✔
1089
               CALL releaseMemberList(self)
13✔
1090
               self % list => list
13✔
1091
               CALL self % list % retain()
13✔
1092
               CALL self % setToStart
13✔
1093
            ELSE
1094
               self % list => list
9✔
1095
               CALL self % list % retain()
9✔
1096
               CALL self % setToStart()
9✔
1097
            END IF 
1098
            
1099
         ELSE
1100
         
NEW
1101
            IF( ASSOCIATED(self % list) )     THEN
×
NEW
1102
               CALL releaseMemberList(self)
×
1103
            END IF 
NEW
1104
            self % list => NULL()
×
1105
            
1106
         END IF
1107
         
1108
      END SUBROUTINE setLinkedListClass   
37✔
1109
!
1110
!////////////////////////////////////////////////////////////////////////
1111
!
NEW
1112
      SUBROUTINE setLinkedList(self,list)
×
1113
         IMPLICIT NONE 
1114
         CLASS(FTLinkedListIterator)  :: self
1115
         TYPE (FTLinkedList), POINTER :: list
1116
!
1117
!        -----------------------------------
1118
!        Remove current list if there is one
1119
!        -----------------------------------
1120
!
UNCOV
1121
         IF ( ASSOCIATED(list) )     THEN
×
1122
         
UNCOV
1123
            IF ( ASSOCIATED(self % list, list) )     THEN
×
UNCOV
1124
               CALL self % setToStart()
×
UNCOV
1125
            ELSE IF( ASSOCIATED(self % list) )     THEN
×
UNCOV
1126
               CALL releaseMemberList(self)
×
UNCOV
1127
               self % list => list
×
UNCOV
1128
               CALL self % list % retain()
×
UNCOV
1129
               CALL self % setToStart
×
1130
            ELSE
UNCOV
1131
               self % list => list
×
UNCOV
1132
               CALL self % list % retain()
×
UNCOV
1133
               CALL self % setToStart()
×
1134
            END IF 
1135
            
1136
         ELSE
1137
         
1138
            IF( ASSOCIATED(self % list) )     THEN
×
1139
               CALL releaseMemberList(self)
×
1140
            END IF 
1141
            self % list => NULL()
×
1142
            
1143
         END IF
1144
         
UNCOV
1145
      END SUBROUTINE setLinkedList   
×
1146
!
1147
!////////////////////////////////////////////////////////////////////////
1148
!
1149
      FUNCTION returnLinkedList(self) RESULT(o)
1✔
1150
         IMPLICIT NONE 
1151
         CLASS(FTLinkedListIterator)  :: self
1152
         CLASS(FTLinkedList), POINTER     :: o
1153
         o => self % list
1✔
1154
      END FUNCTION returnLinkedList 
1✔
1155
!
1156
!////////////////////////////////////////////////////////////////////////
1157
!
1158
      FUNCTION FTLinkedListObject(self) RESULT(o)
123✔
1159
         IMPLICIT NONE 
1160
         CLASS(FTLinkedListIterator)  :: self
1161
         CLASS(FTObject), POINTER     :: o
1162
         o => self % current % recordObject
123✔
1163
      END FUNCTION FTLinkedListObject 
123✔
1164
!
1165
!////////////////////////////////////////////////////////////////////////
1166
!
1167
      FUNCTION FTLinkedListCurrentRecord(self) RESULT(o)
1✔
1168
         IMPLICIT NONE 
1169
         CLASS(FTLinkedListIterator)        :: self
1170
         CLASS(FTLinkedListRecord), POINTER :: o
1171
         o => self % current
1✔
1172
      END FUNCTION FTLinkedListCurrentRecord 
1✔
1173
!
1174
!//////////////////////////////////////////////////////////////////////// 
1175
! 
1176
      SUBROUTINE removeCurrentRecord(self)  
3✔
1177
         IMPLICIT NONE  
1178
         CLASS(FTLinkedListIterator)        :: self
1179
         CLASS(FTLinkedListRecord), POINTER :: r, n
1180
         r => self % current
3✔
1181
         n => self % current % next
3✔
1182
         
1183
         CALL self % list % removeRecord(r)
3✔
1184
         self % current => n
3✔
1185
         
1186
      END SUBROUTINE removeCurrentRecord
3✔
1187
!
1188
!//////////////////////////////////////////////////////////////////////// 
1189
! 
1190
!      -----------------------------------------------------------------
1191
!> Class name returns a string with the name of the type of the object
1192
!>
1193
!>  ### Usage:
1194
!>
1195
!>        PRINT *,  obj % className()
1196
!>        if( obj % className = "FTLinkedListIterator")
1197
!>
1198
      FUNCTION linkedListIteratorClassName(self)  RESULT(s)
1✔
1199
         IMPLICIT NONE  
1200
         CLASS(FTLinkedListIterator)                :: self
1201
         CHARACTER(LEN=CLASS_NAME_CHARACTER_LENGTH) :: s
1202
         
1203
         s = "FTLinkedListIterator"
1✔
1204
 
1205
      END FUNCTION linkedListIteratorClassName
1✔
1206
      
1207
      END MODULE FTLinkedListIteratorClass   
10✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc