Skip to content

Commit 6d55e7b

Browse files
Christian Hovyhavogt
Christian Hovy
authored andcommitted
[Fortran] [FTG] Support for strings in Fortran (#205)
`CHARACTER`s are converted with `IACHAR` and stored as integer array.
1 parent cab85c5 commit 6d55e7b

File tree

6 files changed

+240
-2
lines changed

6 files changed

+240
-2
lines changed

src/serialbox-fortran/m_ser_ftg.f90

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ MODULE m_ser_ftg
120120

121121
INTERFACE ftg_write
122122
MODULE PROCEDURE &
123+
ftg_write_string, &
123124
ftg_write_logical_0d, &
124125
ftg_write_logical_1d, &
125126
ftg_write_logical_2d, &
@@ -154,6 +155,7 @@ MODULE m_ser_ftg
154155

155156
INTERFACE ftg_read
156157
MODULE PROCEDURE &
158+
ftg_read_string, &
157159
ftg_read_logical_0d, &
158160
ftg_read_logical_1d, &
159161
ftg_read_logical_2d, &
@@ -785,6 +787,27 @@ END FUNCTION ftg_loc_hex
785787
!=============================================================================
786788
!=============================================================================
787789

790+
SUBROUTINE ftg_write_string(fieldname, field)
791+
CHARACTER(LEN=*), INTENT(IN) :: fieldname
792+
CHARACTER(LEN=*), INTENT(IN), TARGET :: field
793+
794+
CHARACTER(LEN=LEN(field)), POINTER :: padd
795+
LOGICAL :: bullshit
796+
797+
padd => field
798+
bullshit = .FALSE.
799+
IF (ignore_bullshit) THEN
800+
bullshit = .NOT. ASSOCIATED(padd)
801+
END IF
802+
803+
IF (.NOT. bullshit) THEN
804+
CALL fs_write_field(ftg_get_serializer(), ftg_get_savepoint(), fieldname, field)
805+
CALL ftg_add_field_metainfo(TRIM(fieldname), 'ftg:registered_only', .FALSE.)
806+
CALL ftg_add_field_metainfo(TRIM(fieldname), 'ftg:loc', TRIM(ADJUSTL(ftg_loc_hex(C_LOC(field)))))
807+
END IF
808+
809+
END SUBROUTINE ftg_write_string
810+
788811
SUBROUTINE ftg_write_logical_0d(fieldname, field)
789812
CHARACTER(LEN=*), INTENT(IN) :: fieldname
790813
LOGICAL, INTENT(IN), TARGET :: field
@@ -1670,6 +1693,20 @@ END SUBROUTINE ftg_write_double_4d
16701693
!=============================================================================
16711694
!=============================================================================
16721695

1696+
SUBROUTINE ftg_read_string(fieldname, field, rperturb)
1697+
CHARACTER(LEN=*), INTENT(IN) :: fieldname
1698+
CHARACTER(LEN=*), INTENT(OUT), TARGET :: field
1699+
REAL, INTENT(IN), OPTIONAL :: rperturb
1700+
LOGICAL :: registered_only
1701+
1702+
IF (.NOT. ignore_not_existing .OR. ftg_field_exists(fieldname)) THEN
1703+
CALL ftg_get_field_metainfo(fieldname, 'ftg:registered_only', registered_only)
1704+
IF (.NOT. registered_only) THEN
1705+
CALL fs_read_field(serializer, savepoint, fieldname, field, rperturb)
1706+
END IF
1707+
END IF
1708+
END SUBROUTINE ftg_read_string
1709+
16731710
SUBROUTINE ftg_read_logical_0d(fieldname, field, rperturb)
16741711
CHARACTER(LEN=*), INTENT(IN) :: fieldname
16751712
LOGICAL, INTENT(OUT), TARGET :: field

src/serialbox-fortran/m_ser_ftg_cmp.f90

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ MODULE m_ser_ftg_cmp
7878

7979
INTERFACE ftg_compare
8080
MODULE PROCEDURE &
81+
ftg_compare_string, &
8182
ftg_compare_logical_0d, &
8283
ftg_compare_logical_1d, &
8384
ftg_compare_logical_2d, &
@@ -1219,6 +1220,62 @@ END SUBROUTINE ftg_cmp_print_deviations_double_4d
12191220
!=============================================================================
12201221
!=============================================================================
12211222

1223+
SUBROUTINE ftg_compare_string(fieldname, field, result, failure_count, fieldname_alias)
1224+
CHARACTER(LEN=*), INTENT(IN) :: fieldname
1225+
CHARACTER(LEN=*), INTENT(IN) :: field
1226+
LOGICAL, INTENT(OUT) :: result
1227+
INTEGER, INTENT(INOUT), OPTIONAL :: failure_count
1228+
CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: fieldname_alias
1229+
CHARACTER(LEN=256) :: fieldname_print
1230+
CHARACTER(LEN=LEN(field)) :: stored_field
1231+
1232+
IF (PRESENT(fieldname_alias)) THEN
1233+
fieldname_print = fieldname_alias
1234+
ELSE
1235+
fieldname_print = fieldname
1236+
END IF
1237+
1238+
result = .TRUE.
1239+
1240+
IF (.NOT. ftg_field_exists(fieldname)) THEN
1241+
IF (ftg_cmp_count_missing_field_as_failure) THEN
1242+
result = .FALSE.
1243+
END IF
1244+
IF (.NOT. ftg_cmp_quiet) THEN
1245+
WRITE (*,'(A,A,A,A)') TRIM(ftg_cmp_message_prefix), " ", TRIM(fieldname_print), " : Don't exist in Serializer"
1246+
END IF
1247+
ELSE
1248+
CALL ftg_read(fieldname, stored_field)
1249+
IF (.NOT. ftg_cmp_size(fieldname, (/ LEN(field) /), fieldname_print)) THEN
1250+
result = .FALSE.
1251+
ELSE IF (field /= stored_field) THEN
1252+
result = .FALSE.
1253+
IF (.NOT. ftg_cmp_quiet) THEN
1254+
WRITE (*,'(A,A,A,A)') TRIM(ftg_cmp_message_prefix), " ", TRIM(fieldname_print), " : Not equal"
1255+
IF (ftg_cmp_max_print_deviations > 0) THEN
1256+
WRITE (*,'(A)',advance="no") ' -> expected: "'
1257+
WRITE (*,'(A)',advance="no") TRIM(stored_field)
1258+
WRITE (*,'(A)') '"'
1259+
WRITE (*,'(A)',advance="no") ' actual: "'
1260+
WRITE (*,'(A)',advance="no") TRIM(field)
1261+
WRITE (*,'(A)') '"'
1262+
END IF
1263+
END IF
1264+
END IF
1265+
END IF
1266+
1267+
IF (result) THEN
1268+
IF (.NOT. ftg_cmp_quiet .AND. ftg_cmp_print_when_equal) THEN
1269+
WRITE (*,'(A,A,A,A,A,A)') TRIM(ftg_cmp_message_prefix), ' ', TRIM(fieldname_print), ' : OK ("', TRIM(field), '")'
1270+
END IF
1271+
ELSE
1272+
IF (PRESENT(failure_count)) THEN
1273+
failure_count = failure_count + 1
1274+
END IF
1275+
END IF
1276+
1277+
END SUBROUTINE ftg_compare_string
1278+
12221279
SUBROUTINE ftg_compare_logical_0d(fieldname, field, result, failure_count, fieldname_alias)
12231280
CHARACTER(LEN=*), INTENT(IN) :: fieldname
12241281
LOGICAL, INTENT(IN) :: field
@@ -3009,4 +3066,4 @@ SUBROUTINE ftg_compare_double_4d(fieldname, field, result, failure_count, lbound
30093066

30103067
END SUBROUTINE ftg_compare_double_4d
30113068

3012-
END MODULE m_ser_ftg_cmp
3069+
END MODULE m_ser_ftg_cmp

src/serialbox-fortran/m_serialize.f90

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ END SUBROUTINE fs_disable_serialization
224224
!------------------------------------------------------------------------------
225225
INTERFACE fs_write_field
226226
MODULE PROCEDURE &
227+
fs_write_string, &
227228
fs_write_logical_0d, &
228229
fs_write_logical_1d, &
229230
fs_write_logical_2d, &
@@ -262,6 +263,7 @@ END SUBROUTINE fs_disable_serialization
262263
!------------------------------------------------------------------------------
263264
INTERFACE fs_read_field
264265
MODULE PROCEDURE &
266+
fs_read_string, &
265267
fs_read_logical_0d, &
266268
fs_read_logical_1d, &
267269
fs_read_logical_2d, &
@@ -1516,6 +1518,27 @@ END SUBROUTINE fs_get_savepoint_metainfo_d
15161518
!=============================================================================
15171519
!=============================================================================
15181520

1521+
SUBROUTINE fs_write_string(serializer, savepoint, fieldname, field)
1522+
TYPE(t_serializer), INTENT(IN) :: serializer
1523+
TYPE(t_savepoint) , INTENT(IN) :: savepoint
1524+
CHARACTER(LEN=*), INTENT(IN) :: fieldname
1525+
CHARACTER(LEN=*, KIND=C_CHAR), INTENT(IN), TARGET :: field
1526+
1527+
! Local variables
1528+
INTEGER(KIND=C_INT), ALLOCATABLE :: ascii(:)
1529+
INTEGER :: i
1530+
1531+
ALLOCATE(ascii(LEN(field)))
1532+
DO i = 1, LEN(field)
1533+
ascii(i) = IACHAR(field(i:i), C_INT)
1534+
END DO
1535+
CALL fs_write_field(serializer, savepoint, fieldname, ascii)
1536+
1537+
END SUBROUTINE fs_write_string
1538+
1539+
!=============================================================================
1540+
!=============================================================================
1541+
15191542
SUBROUTINE fs_write_logical_0d(serializer, savepoint, fieldname, field)
15201543
TYPE(t_serializer), INTENT(IN) :: serializer
15211544
TYPE(t_savepoint) , INTENT(IN) :: savepoint
@@ -2300,6 +2323,33 @@ END SUBROUTINE fs_write_double_4d
23002323
!=============================================================================
23012324
!=============================================================================
23022325

2326+
SUBROUTINE fs_read_string(serializer, savepoint, fieldname, field, rperturb)
2327+
TYPE(t_serializer), INTENT(IN) :: serializer
2328+
TYPE(t_savepoint) , INTENT(IN) :: savepoint
2329+
CHARACTER(LEN=*), INTENT(IN) :: fieldname
2330+
CHARACTER(LEN=*, KIND=C_CHAR), INTENT(OUT), TARGET :: field
2331+
REAL, INTENT(IN), OPTIONAL :: rperturb
2332+
2333+
! Local variables
2334+
INTEGER(KIND=C_INT), ALLOCATABLE :: ascii(:)
2335+
INTEGER :: i
2336+
2337+
ALLOCATE(ascii(fs_get_total_size(serializer, fieldname)))
2338+
CALL fs_read_field(serializer, savepoint, fieldname, ascii)
2339+
DO i = 1, MIN(LEN(field), SIZE(ascii))
2340+
field(i:i) = ACHAR(ascii(i), C_CHAR)
2341+
END DO
2342+
IF (LEN(field) > SIZE(ascii)) THEN
2343+
DO i = LEN(field) + 1, SIZE(ascii)
2344+
field(i:i) = ' '
2345+
END DO
2346+
END IF
2347+
2348+
END SUBROUTINE fs_read_string
2349+
2350+
!=============================================================================
2351+
!=============================================================================
2352+
23032353
SUBROUTINE fs_read_logical_0d(serializer, savepoint, fieldname, field, rperturb)
23042354
TYPE(t_serializer), INTENT(IN) :: serializer
23052355
TYPE(t_savepoint) , INTENT(IN) :: savepoint

test/serialbox-fortran/ser_ftg_cmp_test.pf

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,5 +353,39 @@ CONTAINS
353353
CALL ftg_destroy_serializer()
354354

355355
END SUBROUTINE testNotExists
356+
357+
@Test
358+
SUBROUTINE testStrings()
359+
360+
LOGICAL :: result
361+
INTEGER :: failure_count
362+
363+
CHARACTER(10) :: w_testfield_len10
364+
365+
CHARACTER(len=*), PARAMETER :: base_name = 'test_strings'
366+
367+
result = .FALSE.
368+
failure_count = 0
369+
370+
371+
w_testfield_len10 = 'abcde'
372+
373+
CALL ftg_set_serializer(dir, base_name, 'w')
374+
CALL ftg_write("testfield_len10", w_testfield_len10)
375+
CALL ftg_destroy_serializer()
376+
377+
CALL ftg_set_serializer(dir, base_name, 'r')
378+
CALL ftg_compare("testfield_len10", "abcde ", result, failure_count)
379+
@assertTrue(result)
380+
@assertEqual(0, failure_count)
381+
CALL ftg_compare("testfield_len10", "abcdedefgh", result, failure_count)
382+
@assertFalse(result)
383+
@assertEqual(1, failure_count)
384+
CALL ftg_compare("testfield_len10", "abcde", result, failure_count)
385+
@assertFalse(result)
386+
@assertEqual(2, failure_count)
387+
CALL ftg_destroy_serializer()
388+
389+
END SUBROUTINE testStrings
356390

357391
END MODULE ser_ftg_cmp_test

test/serialbox-fortran/ser_ftg_test.pf

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,35 @@ CONTAINS
11111111
@assertTrue(ftg_field_exists("testc2"))
11121112
CALL ftg_destroy_serializer()
11131113

1114-
END SUBROUTINE testTypeComponents
1114+
END SUBROUTINE testTypeComponents
1115+
1116+
@Test
1117+
SUBROUTINE testStrings()
1118+
1119+
CHARACTER(10) :: w_testfield_len10, r_testfield_len10
1120+
1121+
CHARACTER(len=*), PARAMETER :: base_name = 'test_strings'
1122+
1123+
w_testfield_len10 = 'abcde'
1124+
1125+
CALL ftg_set_serializer(dir, base_name, 'w')
1126+
CALL ftg_write("testfield_len10", w_testfield_len10)
1127+
CALL ftg_destroy_serializer()
1128+
1129+
CALL ftg_set_serializer(dir, base_name, 'r')
1130+
1131+
@assertTrue(ftg_field_exists("testfield_len10"))
1132+
@assertEqual((/ 10, 0, 0, 0 /), ftg_get_size("testfield_len10"))
1133+
1134+
CALL ftg_read("testfield_len10", r_testfield_len10)
1135+
1136+
CALL ftg_destroy_serializer()
1137+
1138+
@assertEqual('a', CHAR(ICHAR('a')))
1139+
@assertEqual(w_testfield_len10, r_testfield_len10)
1140+
@assertEqual('abcde ', r_testfield_len10)
1141+
@assertEqual('abcde', TRIM(r_testfield_len10))
1142+
1143+
END SUBROUTINE testStrings
11151144

11161145
END MODULE ser_ftg_test

test/serialbox-fortran/serialbox_test.pf

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,5 +838,36 @@ CONTAINS
838838
CALL fs_destroy_savepoint(savepoint)
839839

840840
END SUBROUTINE testSavepointMetainfo
841+
842+
@Test
843+
SUBROUTINE testStrings()
844+
845+
TYPE(t_serializer) :: serializer
846+
CHARACTER(10) :: w_testfield_len10, r_testfield_len10
847+
848+
CHARACTER(len=*), PARAMETER :: base_name = 'test_strings'
849+
850+
w_testfield_len10 = 'abcde'
851+
852+
CALL fs_create_serializer(dir, base_name, 'w', serializer)
853+
CALL fs_write_field(serializer, savepoint, "testfield_len10", w_testfield_len10)
854+
CALL fs_destroy_serializer(serializer)
855+
856+
CALL fs_create_serializer(dir, base_name, 'r', serializer)
857+
858+
@assertTrue(fs_field_exists(serializer, "testfield_len10"))
859+
@assertEqual(10, fs_get_total_size(serializer, "testfield_len10"))
860+
@assertEqual((/ 10, 0, 0, 0 /), fs_get_size(serializer, "testfield_len10"))
861+
862+
CALL fs_read_field(serializer, savepoint, "testfield_len10", r_testfield_len10)
863+
864+
CALL fs_destroy_serializer(serializer)
865+
866+
@assertEqual('a', CHAR(ICHAR('a')))
867+
@assertEqual(w_testfield_len10, r_testfield_len10)
868+
@assertEqual('abcde ', r_testfield_len10)
869+
@assertEqual('abcde', TRIM(r_testfield_len10))
870+
871+
END SUBROUTINE testStrings
841872

842873
END MODULE serialbox_test

0 commit comments

Comments
 (0)