Skip to content

Commit be91cdc

Browse files
committed
Merge branch 'master' of https://github.com/jacobwilliams/json-fortran into 606-close-if-open
2 parents e1534e5 + 840eb7e commit be91cdc

File tree

3 files changed

+233
-81
lines changed

3 files changed

+233
-81
lines changed

src/json_parameters.F90

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ module json_parameters
9999
character(kind=CK,len=*),parameter :: false_str = CK_'false' !! JSON logical False string
100100
#endif
101101

102-
integer, private :: i_ !! just a counter for `control_chars` array
103-
character(kind=CK,len=*),dimension(32),parameter :: control_chars = &
104-
[(achar(i_,kind=CK),i_=1,31), achar(127,kind=CK)] !! Control characters, possibly in unicode
102+
! integer, private :: i_ !! just a counter for `control_chars` array
103+
! character(kind=CK,len=*),dimension(32),parameter :: control_chars = &
104+
! [(achar(i_,kind=CK),i_=1,31), achar(127,kind=CK)] !! Control characters, possibly in unicode
105105

106106
!find out the precision of the floating point number system
107107
!and set safety factors

src/json_string_utilities.F90

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ module json_string_utilities
6464
public :: real_to_string
6565
public :: string_to_integer
6666
public :: string_to_real
67+
#ifdef C_STR2REAL
68+
public :: string_to_real_c
69+
#endif
6770
public :: valid_json_hex
6871
public :: to_unicode
6972
public :: escape_string
@@ -234,6 +237,7 @@ subroutine string_to_real(str,use_quiet_nan,rval,status_ok)
234237
integer(IK) :: ierr !! read iostat error code
235238

236239
read(str,fmt=*,iostat=ierr) rval
240+
237241
status_ok = (ierr==0)
238242
if (.not. status_ok) then
239243
rval = 0.0_RK
@@ -253,6 +257,147 @@ subroutine string_to_real(str,use_quiet_nan,rval,status_ok)
253257
end subroutine string_to_real
254258
!*****************************************************************************************
255259

260+
#ifdef C_STR2REAL
261+
!*****************************************************************************************
262+
!> author: Jacob Williams
263+
! date: 11/05/2021
264+
!
265+
! Convert a string into a `real(RK)`.
266+
! This version uses `strtof`, `strtod`, or `strtold` from C.
267+
! It will fall back to using `read(fmt=*)` if any errors.
268+
!
269+
!# History
270+
! * Jacob Williams : 11/05/2021 : created by modification of [[string_to_real]].
271+
272+
subroutine string_to_real_c(str,use_quiet_nan,rval,status_ok)
273+
274+
use iso_c_binding, only: c_double, c_float, c_long_double, &
275+
c_char, c_ptr, c_null_ptr, c_long, &
276+
c_null_char, c_loc, c_associated
277+
278+
implicit none
279+
280+
character(kind=CK,len=*),intent(in) :: str !! the string to convert to a real
281+
logical(LK),intent(in) :: use_quiet_nan !! if true, return NaN's as `ieee_quiet_nan`.
282+
!! otherwise, use `ieee_signaling_nan`.
283+
real(RK),intent(out) :: rval !! `str` converted to a real value
284+
logical(LK),intent(out) :: status_ok !! true if there were no errors
285+
286+
integer(IK) :: ierr !! read iostat error code
287+
type(c_ptr) :: endptr !! pointer arg to `strtof`, etc.
288+
character(kind=c_char,len=:),allocatable,target :: c_str !! for null-terminated C string
289+
type(c_ptr) :: str_start !! pointer to start of string for comparison
290+
logical :: done !! if the string has been processed
291+
292+
interface
293+
function strtof( str, endptr ) result(d) bind(C, name="strtof" )
294+
!! <stdlib.h> :: float strtof(const char *str, char **endptr)
295+
import
296+
character(kind=c_char,len=1),dimension(*),intent(in) :: str
297+
type(c_ptr), intent(inout) :: endptr
298+
real(c_float) :: d
299+
end function strtof
300+
function strtod( str, endptr ) result(d) bind(C, name="strtod" )
301+
!! <stdlib.h> :: double strtod(const char *str, char **endptr)
302+
import
303+
character(kind=c_char,len=1),dimension(*),intent(in) :: str
304+
type(c_ptr), intent(inout) :: endptr
305+
real(c_double) :: d
306+
end function strtod
307+
function strtold( str, endptr ) result(d) bind(C, name="strtold" )
308+
!! <stdlib.h> :: long double strtold(const char *str, char **endptr)
309+
import
310+
character(kind=c_char,len=1),dimension(*),intent(in) :: str
311+
type(c_ptr), intent(inout) :: endptr
312+
real(c_long_double) :: d
313+
end function strtold
314+
end interface
315+
316+
#ifdef USE_UCS4
317+
! if using unicode, don't try to call the C routines
318+
! [not sure they will work? need to test this... what if c_char /= CK?]
319+
call string_to_real(str,use_quiet_nan,rval,status_ok)
320+
return
321+
#endif
322+
323+
! Create null-terminated C string
324+
c_str = trim(str)//C_NULL_CHAR
325+
str_start = c_loc(c_str)
326+
endptr = c_null_ptr
327+
done = .false.
328+
329+
#ifdef REAL32
330+
331+
! single precision
332+
333+
if (RK == c_float) then
334+
rval = strtof( c_str, endptr )
335+
! Check if conversion was successful:
336+
! endptr should not point to the start (no conversion) and should not be null
337+
if (c_associated(endptr) .and. .not. c_associated(endptr, str_start)) then
338+
ierr = 0
339+
status_ok = .true.
340+
done = .true.
341+
end if
342+
end if
343+
344+
#elif REAL128
345+
346+
! quad precision
347+
348+
if (RK == c_long_double) then
349+
rval = strtold( c_str, endptr )
350+
! Check if conversion was successful:
351+
if (c_associated(endptr) .and. .not. c_associated(endptr, str_start)) then
352+
ierr = 0
353+
status_ok = .true.
354+
done = .true.
355+
end if
356+
end if
357+
358+
#else
359+
360+
! double precision
361+
362+
if (RK == c_double) then
363+
rval = strtod( c_str, endptr )
364+
! Check if conversion was successful:
365+
if (c_associated(endptr) .and. .not. c_associated(endptr, str_start)) then
366+
ierr = 0
367+
status_ok = .true.
368+
done = .true.
369+
end if
370+
end if
371+
372+
#endif
373+
374+
if (allocated(c_str)) deallocate(c_str)
375+
376+
if (.not. done) then
377+
! the string was not processed, fallback to read:
378+
read(str,fmt=*,iostat=ierr) rval
379+
status_ok = (ierr==0)
380+
end if
381+
382+
if (.not. status_ok) then
383+
rval = 0.0_RK
384+
else
385+
if (ieee_support_nan(rval)) then
386+
if (ieee_is_nan(rval)) then
387+
! make sure to return the correct NaN
388+
if (use_quiet_nan) then
389+
rval = ieee_value(rval,ieee_quiet_nan)
390+
else
391+
rval = ieee_value(rval,ieee_signaling_nan)
392+
end if
393+
end if
394+
end if
395+
end if
396+
397+
end subroutine string_to_real_c
398+
!*****************************************************************************************
399+
#endif
400+
256401
!*****************************************************************************************
257402
!> author: Izaak Beekman
258403
! date: 02/24/2015

0 commit comments

Comments
 (0)