11
11
12
12
module json_string_utilities
13
13
14
+ use ,intrinsic :: ieee_arithmetic
14
15
use json_kinds
15
16
use json_parameters
16
17
@@ -148,33 +149,61 @@ end subroutine string_to_integer
148
149
! Convert a real value to a string.
149
150
!
150
151
! ### Modified
151
- ! * Izaak Beekman : 02/24/2015 : added the compact option.
152
+ ! * Izaak Beekman : 02/24/2015 : added the compact option.
152
153
! * Jacob Williams : 10/27/2015 : added the star option.
154
+ ! * Jacob Williams : 07/07/2019 : added null and ieee options.
153
155
154
- subroutine real_to_string (rval ,real_fmt ,compact_real ,str )
156
+ subroutine real_to_string (rval ,real_fmt ,compact_real ,non_normals_to_null , str )
155
157
156
158
implicit none
157
159
158
160
real (RK),intent (in ) :: rval ! ! real value.
159
161
character (kind= CDK,len=* ),intent (in ) :: real_fmt ! ! format for real numbers
160
162
logical (LK),intent (in ) :: compact_real ! ! compact the string so that it is
161
163
! ! displayed with fewer characters
164
+ logical (LK),intent (in ) :: non_normals_to_null ! ! If True, NaN, Infinity, or -Infinity are returned as `null`.
165
+ ! ! If False, the string value will be returned in quotes
166
+ ! ! (e.g., "NaN", "Infinity", or "-Infinity" )
162
167
character (kind= CK,len=* ),intent (out ) :: str ! ! `rval` converted to a string.
163
168
164
- integer (IK) :: istat
169
+ integer (IK) :: istat ! ! write `iostat` flag
165
170
166
- if (real_fmt== star) then
167
- write (str,fmt=* ,iostat= istat) rval
168
- else
169
- write (str,fmt= real_fmt,iostat= istat) rval
170
- end if
171
+ if (ieee_is_finite(rval) .and. .not. ieee_is_nan(rval)) then
172
+
173
+ ! normal real numbers
174
+
175
+ if (real_fmt== star) then
176
+ write (str,fmt=* ,iostat= istat) rval
177
+ else
178
+ write (str,fmt= real_fmt,iostat= istat) rval
179
+ end if
180
+
181
+ if (istat== 0 ) then
182
+ ! in this case, the default string will be compacted,
183
+ ! so that the same value is displayed with fewer characters.
184
+ if (compact_real) call compact_real_string(str)
185
+ else
186
+ str = repeat (star,len (str)) ! error
187
+ end if
171
188
172
- if (istat== 0 ) then
173
- ! in this case, the default string will be compacted,
174
- ! so that the same value is displayed with fewer characters.
175
- if (compact_real) call compact_real_string(str)
176
189
else
177
- str = repeat (star,len (str))
190
+ ! special cases for NaN, Infinity, and -Infinity
191
+
192
+ if (non_normals_to_null) then
193
+ ! return it as a JSON null value
194
+ str = null_str
195
+ else
196
+ ! Let the compiler do the real to string conversion
197
+ ! like before, but put the result in quotes so it
198
+ ! gets printed as a string
199
+ write (str,fmt=* ,iostat= istat) rval
200
+ if (istat== 0 ) then
201
+ str = quotation_mark// trim (adjustl (str))// quotation_mark
202
+ else
203
+ str = repeat (star,len (str)) ! error
204
+ end if
205
+ end if
206
+
178
207
end if
179
208
180
209
end subroutine real_to_string
@@ -192,19 +221,34 @@ end subroutine real_to_string
192
221
! (e.g., when `str='1E-5'`).
193
222
! * Jacob Williams : 2/6/2017 : moved core logic to this routine.
194
223
195
- subroutine string_to_real (str ,rval ,status_ok )
224
+ subroutine string_to_real (str ,use_quiet_nan , rval ,status_ok )
196
225
197
226
implicit none
198
227
199
- character (kind= CK,len=* ),intent (in ) :: str ! ! the string to convert to a real
200
- real (RK),intent (out ) :: rval ! ! `str` converted to a real value
201
- logical (LK),intent (out ) :: status_ok ! ! true if there were no errors
228
+ character (kind= CK,len=* ),intent (in ) :: str ! ! the string to convert to a real
229
+ logical (LK),intent (in ) :: use_quiet_nan ! ! if true, return NaN's as `ieee_quiet_nan`.
230
+ ! ! otherwise, use `ieee_signaling_nan`.
231
+ real (RK),intent (out ) :: rval ! ! `str` converted to a real value
232
+ logical (LK),intent (out ) :: status_ok ! ! true if there were no errors
202
233
203
234
integer (IK) :: ierr ! ! read iostat error code
204
235
205
236
read (str,fmt=* ,iostat= ierr) rval
206
237
status_ok = (ierr== 0 )
207
- if (.not. status_ok) rval = 0.0_RK
238
+ if (.not. status_ok) then
239
+ rval = 0.0_RK
240
+ else
241
+ if (ieee_support_nan(rval)) then
242
+ if (ieee_is_nan(rval)) then
243
+ ! make sure to return the correct NaN
244
+ if (use_quiet_nan) then
245
+ rval = ieee_value(rval,ieee_quiet_nan)
246
+ else
247
+ rval = ieee_value(rval,ieee_signaling_nan)
248
+ end if
249
+ end if
250
+ end if
251
+ end if
208
252
209
253
end subroutine string_to_real
210
254
! *****************************************************************************************
0 commit comments