6 use iso_fortran_env
, only : stdout=>output_unit, stderr=>error_unit
8 implicit none ;
private 10 public lowercase, uppercase
11 public left_int, left_ints
12 public left_real, left_reals
13 public string_functions_unit_tests
16 public extract_integer
25 function lowercase(input_string)
26 character(len=*),
intent(in) :: input_string
27 character(len=len(input_string)) :: lowercase
31 integer,
parameter :: co=iachar(
'a')-iachar(
'A')
34 lowercase = input_string
35 do k=1, len_trim(input_string)
36 if (lowercase(k:k) >=
'A' .and. lowercase(k:k) <=
'Z') &
37 lowercase(k:k) = achar(ichar(lowercase(k:k))+co)
39 end function lowercase
43 function uppercase(input_string)
44 character(len=*),
intent(in) :: input_string
45 character(len=len(input_string)) :: uppercase
49 integer,
parameter :: co=iachar(
'A')-iachar(
'a')
52 uppercase = input_string
53 do k=1, len_trim(input_string)
54 if (uppercase(k:k) >=
'a' .and. uppercase(k:k) <=
'z') &
55 uppercase(k:k) = achar(ichar(uppercase(k:k))+co)
57 end function uppercase
62 integer,
intent(in) :: i
63 character(len=19) :: left_int
65 character(len=19) :: tmp
66 write(tmp(1:19),
'(I19)') i
67 write(left_int(1:19),
'(A)') adjustl(tmp)
73 integer,
intent(in) :: i(:)
74 character(len=1320) :: left_ints
76 character(len=1320) :: tmp
78 write(left_ints(1:1320),
'(A)') trim(left_int(i(1)))
82 write(left_ints(1:1320),
'(A,", ",A)') trim(tmp),trim(left_int(i(j)))
85 end function left_ints
88 function left_real(val)
89 real,
intent(in) :: val
90 character(len=32) :: left_real
94 if ((abs(val) < 1.0e4) .and. (abs(val) >= 1.0e-3))
then 95 write(left_real,
'(F30.11)') val
96 if (.not.isformattedfloatequalto(left_real,val))
then 97 write(left_real,
'(F30.12)') val
98 if (.not.isformattedfloatequalto(left_real,val))
then 99 write(left_real,
'(F30.13)') val
100 if (.not.isformattedfloatequalto(left_real,val))
then 101 write(left_real,
'(F30.14)') val
102 if (.not.isformattedfloatequalto(left_real,val))
then 103 write(left_real,
'(F30.15)') val
104 if (.not.isformattedfloatequalto(left_real,val))
then 105 write(left_real,
'(F30.16)') val
112 l = len_trim(left_real)
113 if ((l<2) .or. (left_real(l-1:l) ==
".0") .or. &
114 (left_real(l:l) /=
"0"))
exit 117 elseif (val == 0.)
then 120 if ((abs(val) <= 1.0e-100) .or. (abs(val) >= 1.0e100))
then 121 write(left_real(1:32),
'(ES24.14E3)') val
122 if (.not.isformattedfloatequalto(left_real,val)) &
123 write(left_real(1:32),
'(ES24.15E3)') val
125 write(left_real(1:32),
'(ES23.14)') val
126 if (.not.isformattedfloatequalto(left_real,val)) &
127 write(left_real(1:32),
'(ES23.15)') val
130 ind = index(left_real,
"0E")
132 if (left_real(ind-1:ind-1) ==
".")
exit 133 left_real = left_real(1:ind-1)//left_real(ind+1:)
136 left_real = adjustl(left_real)
137 end function left_real
141 function left_reals(r,sep)
142 real,
intent(in) :: r(:)
143 character(len=*),
optional,
intent(in) :: sep
145 character(len=1320) :: left_reals
147 integer :: j, n, b, ns
149 character(len=10) :: separator
151 n=1 ; dowrite=.true. ; left_reals=
'' ; b=1
152 if (
present(sep))
then 153 separator=sep ; ns=len(sep)
155 separator=
', ' ; ns=2
160 if (r(j)==r(j+1))
then 167 write(left_reals(b:),
'(A)') separator
171 write(left_reals(b:),
'(A,"*",A)') trim(left_int(n)),trim(left_real(r(j)))
173 write(left_reals(b:),
'(A)') trim(left_real(r(j)))
175 n=1 ; b=len_trim(left_reals)+1
178 end function left_reals
181 function isformattedfloatequalto(str, val)
182 character(len=*),
intent(in) :: str
183 real,
intent(in) :: val
184 logical :: isFormattedFloatEqualTo
188 isformattedfloatequalto=.false.
189 read(str(1:),*,err=987) scannedval
190 if (scannedval == val) isformattedfloatequalto=.true.
192 end function isformattedfloatequalto
197 character(len=120) function extractword(string, n)
198 character(len=*),
intent(in) :: string
199 integer,
intent(in) :: n
201 extractword = extract_word(string,
' ,', n)
203 end function extractword
208 character(len=120) function extract_word(string, separators, n)
209 character(len=*),
intent(in) :: string
210 character(len=*),
intent(in) :: separators
211 integer,
intent(in) :: n
213 integer :: ns, i, b, e, nw
214 logical :: lastCharIsSeperator
216 lastcharisseperator = .true.
217 ns = len_trim(string)
218 i = 0; b=0; e=0; nw=0
221 if (lastcharisseperator)
then 222 if (verify(string(i:i),separators)==0)
then 225 lastcharisseperator = .false.
230 if (verify(string(i:i),separators)==0)
then 231 lastcharisseperator = .true.
235 extract_word = trim(string(b:e))
241 if (b<=ns .and. nw==n-1) extract_word = trim(string(b:ns))
242 end function extract_word
245 integer function extract_integer(string, separators, n, missing_value)
246 character(len=*),
intent(in) :: string
247 character(len=*),
intent(in) :: separators
248 integer,
intent(in) :: n
249 integer,
optional,
intent(in) :: missing_value
251 integer :: ns, i, b, e, nw
252 character(len=20) :: word
254 word = extract_word(string, separators, n)
256 if (len_trim(word)>0)
then 257 read(word(1:len_trim(word)),*) extract_integer
259 if (
present(missing_value))
then 260 extract_integer = missing_value
266 end function extract_integer
269 real function extract_real(string, separators, n, missing_value)
270 character(len=*),
intent(in) :: string
271 character(len=*),
intent(in) :: separators
272 integer,
intent(in) :: n
273 real,
optional,
intent(in) :: missing_value
275 integer :: ns, i, b, e, nw
276 character(len=20) :: word
278 word = extract_word(string, separators, n)
280 if (len_trim(word)>0)
then 281 read(word(1:len_trim(word)),*) extract_real
283 if (
present(missing_value))
then 284 extract_real = missing_value
290 end function extract_real
293 character(len=120) function remove_spaces(string)
294 character(len=*),
intent(in) :: string
297 logical :: lastCharIsSeperator
298 lastcharisseperator = .true.
299 ns = len_trim(string)
303 if (string(i:i) /=
' ')
then 305 remove_spaces(o:o) = string(i:i)
309 remove_spaces(i:i) =
' ' 311 remove_spaces = trim(remove_spaces)
312 end function remove_spaces
315 logical function string_functions_unit_tests(verbose)
317 logical,
intent(in) :: verbose
319 integer :: i(5) = (/ -1, 1, 3, 3, 0 /)
320 real :: r(8) = (/ 0., 1., -2., 1.3, 3.e-11, 3.e-11, 3.e-11, -5.1e12 /)
324 write(stdout,*)
'==== MOM_string_functions: string_functions_unit_tests ===' 325 fail = fail .or. localtests(v,left_int(-1),
'-1')
326 fail = fail .or. localtests(v,left_ints(i(:)),
'-1, 1, 3, 3, 0')
327 fail = fail .or. localtests(v,left_real(0.),
'0.0')
328 fail = fail .or. localtests(v,left_reals(r(:)),
'0.0, 1.0, -2.0, 1.3, 3*3.0E-11, -5.1E+12')
329 fail = fail .or. localtests(v,left_reals(r(:),sep=
' '),
'0.0 1.0 -2.0 1.3 3*3.0E-11 -5.1E+12')
330 fail = fail .or. localtests(v,left_reals(r(:),sep=
','),
'0.0,1.0,-2.0,1.3,3*3.0E-11,-5.1E+12')
331 fail = fail .or. localtests(v,extractword(
"One Two,Three",1),
"One")
332 fail = fail .or. localtests(v,extractword(
"One Two,Three",2),
"Two")
333 fail = fail .or. localtests(v,extractword(
"One Two,Three",3),
"Three")
334 fail = fail .or. localtests(v,extractword(
"One Two, Three",3),
"Three")
335 fail = fail .or. localtests(v,extractword(
" One Two,Three",1),
"One")
336 fail = fail .or. localtests(v,extract_word(
"One,Two,Three",
",",3),
"Three")
337 fail = fail .or. localtests(v,extract_word(
"One,Two,Three",
",",4),
"")
338 fail = fail .or. localtests(v,remove_spaces(
"1 2 3"),
"123")
339 fail = fail .or. localtests(v,remove_spaces(
" 1 2 3"),
"123")
340 fail = fail .or. localtests(v,remove_spaces(
"1 2 3 "),
"123")
341 fail = fail .or. localtests(v,remove_spaces(
"123"),
"123")
342 fail = fail .or. localtests(v,remove_spaces(
" "),
"")
343 fail = fail .or. localtests(v,remove_spaces(
""),
"")
344 fail = fail .or. localtesti(v,extract_integer(
"1",
"",1),1)
345 fail = fail .or. localtesti(v,extract_integer(
"1,2,3",
",",1),1)
346 fail = fail .or. localtesti(v,extract_integer(
"1,2",
",",2),2)
347 fail = fail .or. localtesti(v,extract_integer(
"1,2",
",",3),0)
348 fail = fail .or. localtesti(v,extract_integer(
"1,2",
",",4,4),4)
349 fail = fail .or. localtestr(v,extract_real(
"1.",
"",1),1.)
350 fail = fail .or. localtestr(v,extract_real(
"1.,2.,3.",
",",1),1.)
351 fail = fail .or. localtestr(v,extract_real(
"1.,2.",
",",2),2.)
352 fail = fail .or. localtestr(v,extract_real(
"1.,2.",
",",3),0.)
353 fail = fail .or. localtestr(v,extract_real(
"1.,2.",
",",4,4.),4.)
354 if (.not. fail)
write(stdout,*)
'Pass' 355 string_functions_unit_tests = fail
356 end function string_functions_unit_tests
359 logical function localtests(verbose,str1,str2)
360 logical,
intent(in) :: verbose
361 character(len=*),
intent(in) :: str1
362 character(len=*),
intent(in) :: str2
364 if (trim(str1)/=trim(str2)) localtests=.true.
365 if (localtests .or. verbose)
then 366 write(stdout,*)
'>'//trim(str1)//
'<' 368 write(stdout,*) trim(str1),
':',trim(str2),
'<-- FAIL' 369 write(stderr,*) trim(str1),
':',trim(str2),
'<-- FAIL' 372 end function localtests
375 logical function localtesti(verbose,i1,i2)
376 logical,
intent(in) :: verbose
377 integer,
intent(in) :: i1
378 integer,
intent(in) :: i2
380 if (i1/=i2) localtesti=.true.
381 if (localtesti .or. verbose)
then 382 write(stdout,*) i1,i2
384 write(stdout,*) i1,
'!=',i2,
'<-- FAIL' 385 write(stderr,*) i1,
'!=',i2,
'<-- FAIL' 388 end function localtesti
391 logical function localtestr(verbose,r1,r2)
392 logical,
intent(in) :: verbose
393 real,
intent(in) :: r1
394 real,
intent(in) :: r2
396 if (r1/=r2) localtestr=.true.
397 if (localtestr .or. verbose)
then 398 write(stdout,*) r1,r2
400 write(stdout,*) r1,
'!=',r2,
'<-- FAIL' 401 write(stderr,*) r1,
'!=',r2,
'<-- FAIL' 404 end function localtestr
408 function slasher(dir)
409 character(len=*),
intent(in) :: dir
411 character(len=len(dir)+2) :: slasher
413 if (len_trim(dir) == 0)
then 415 elseif (dir(len_trim(dir):len_trim(dir)) ==
'/')
then 418 slasher = trim(dir)//
"/" Handy functions for manipulating strings.