@@ -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