@@ -116,10 +116,10 @@ module json_module
116
116
! default integer kind [4 bytes]
117
117
integer ,parameter :: IK = int32
118
118
119
- ! default character kind [1 byte]
119
+ ! default character kind [1 byte]
120
120
integer ,parameter :: CK = character_kinds(1 )
121
121
122
- ! default logical kind [4 bytes]
122
+ ! default logical kind [4 bytes]
123
123
! The statement here is to ensure a valid kind
124
124
! if the compiler doesn't have a logical_kinds(3)
125
125
integer ,parameter :: LK = logical_kinds(min (3 ,size (logical_kinds)))
@@ -149,9 +149,19 @@ module json_module
149
149
150
150
integer (IK),parameter :: spaces_per_tab = 2 ! for indenting (Note: jsonlint.com uses 4 spaces)
151
151
152
- integer (IK),parameter :: max_numeric_str_len = 32
153
- character (kind= CK,len=* ),parameter :: real_fmt = ' (E30.16E3)' ! format for real numbers
154
- character (kind= CK,len=* ),parameter :: int_fmt = ' (I10)' ! format for integers
152
+ ! find out the precision of the floating point number system, in io use 4Xprecision
153
+ integer (IK),parameter :: rp_safety_factor = 1
154
+ integer (IK),parameter :: rp_addl_safety = 1
155
+ integer (IK),parameter :: real_precision = rp_safety_factor* precision (1.0_RK ) + rp_addl_safety
156
+ ! Get the number of possible digits in the exponent when using decimal number system
157
+ integer (IK),parameter :: real_exponent_digits = ceiling ( log10 ( &
158
+ real (max (maxexponent (1.0_RK ),abs (minexponent (1.0_RK ))),kind= RK) &
159
+ ) )
160
+ ! 4*precision to prevent rounding errors
161
+ ! 6 = sign + leading 0 + decimal + 'E' + exponent sign + 1 extra
162
+ integer (IK),parameter :: max_numeric_str_len = real_precision + real_exponent_digits + 6
163
+ ! real format set by library initialization
164
+ character (kind= CK,len=* ),parameter :: int_fmt = ' (I0)' ! minimum width format for integers
155
165
character (kind= CK,len=* ),parameter :: star = ' *' ! for invalid numbers
156
166
157
167
! *********************************************************
@@ -532,6 +542,7 @@ end subroutine array_callback_func
532
542
! Note: the following global variables make this module non thread safe.
533
543
!
534
544
545
+ character (kind= CK,len= :),allocatable :: real_fmt
535
546
! exception handling [private variables]
536
547
logical (LK) :: is_verbose = .false. ! if true, all exceptions are immediately printed to console
537
548
logical (LK) :: exception_thrown = .false. ! the error flag
@@ -1234,20 +1245,29 @@ end subroutine json_file_get_string_vec
1234
1245
! AUTHOR
1235
1246
! Jacob Williams : 12/4/2013
1236
1247
!
1248
+ ! MODIFIED
1249
+ ! Izaak Beekman : 02/24/2015
1250
+ !
1237
1251
! SOURCE
1238
1252
1239
1253
subroutine json_initialize (verbose )
1240
1254
1241
1255
implicit none
1242
1256
1243
1257
logical (LK),intent (in ),optional :: verbose ! mainly useful for debugging (default is false)
1244
-
1258
+ character (kind = CK,len = 10 ) :: w,d,e
1245
1259
! optional input (if not present, value remains unchanged):
1246
1260
if (present (verbose)) is_verbose = verbose
1247
1261
1248
1262
! clear any errors from previous runs:
1249
1263
call json_clear_exceptions()
1250
1264
1265
+ ! set the output/input format for reals:
1266
+ write (w,' (I0)' ) max_numeric_str_len
1267
+ write (d,' (I0)' ) real_precision
1268
+ write (e,' (I0)' ) real_exponent_digits
1269
+ real_fmt = ' (e' // trim (w) // ' .' // trim (d) // ' e' // trim (e) // ' )'
1270
+
1251
1271
! Just in case, clear these global variables also:
1252
1272
pushed_index = 0
1253
1273
pushed_char = ' '
@@ -1553,7 +1573,7 @@ subroutine json_value_remove(me,destroy)
1553
1573
1554
1574
if (associated (me% parent)) then
1555
1575
1556
- parent = > me% parent
1576
+ parent = > me% parent
1557
1577
1558
1578
if (associated (me% next)) then
1559
1579
@@ -1562,7 +1582,7 @@ subroutine json_value_remove(me,destroy)
1562
1582
next = > me% next
1563
1583
nullify(me% next)
1564
1584
1565
- if (associated (me% previous)) then
1585
+ if (associated (me% previous)) then
1566
1586
! there are earlier items in the list
1567
1587
previous = > me% previous
1568
1588
previous% next = > next
@@ -2811,7 +2831,7 @@ recursive subroutine json_value_print(this,iunit,str,indent,need_comma,colon,is_
2811
2831
2812
2832
end do
2813
2833
2814
- ! indent the closing array character:
2834
+ ! indent the closing array character:
2815
2835
call write_it( repeat (space, max (0 ,spaces- spaces_per_tab))// end_array,&
2816
2836
comma= print_comma )
2817
2837
nullify(element)
@@ -3696,10 +3716,10 @@ subroutine json_get_string(this, path, value, found)
3696
3716
3697
3717
s = pre// c// post
3698
3718
3699
- n = n-1 ! backslash character has been
3719
+ n = n-1 ! backslash character has been
3700
3720
! removed from the string
3701
3721
3702
- case (' u' ) ! expecting 4 hexadecimal digits after
3722
+ case (' u' ) ! expecting 4 hexadecimal digits after
3703
3723
! the escape character [\uXXXX]
3704
3724
3705
3725
! for now, we are just printing them as is
@@ -3987,7 +4007,7 @@ subroutine json_parse(file, p, unit, str)
3987
4007
return
3988
4008
end if
3989
4009
3990
- iunit = unit
4010
+ iunit = unit
3991
4011
3992
4012
! check to see if the file is already open
3993
4013
! if it is, then use it, otherwise open the file with the name given.
@@ -4614,6 +4634,9 @@ end subroutine to_double
4614
4634
! AUTHOR
4615
4635
! Jacob Williams
4616
4636
!
4637
+ ! MODIFIED
4638
+ ! Izaak Beekman : 02/24/2015
4639
+ !
4617
4640
! SOURCE
4618
4641
4619
4642
subroutine to_string (me ,val ,name )
@@ -5233,7 +5256,7 @@ recursive function pop_char(unit, str, eof, skip_ws) result(popped)
5233
5256
5234
5257
end if
5235
5258
5236
- if (iachar (c) <= 31 ) then ! JW : fixed so it will read spaces
5259
+ if (iachar (c) <= 31 ) then ! JW : fixed so it will read spaces
5237
5260
! in the string (was 32)
5238
5261
5239
5262
! non printing ascii characters
@@ -5348,12 +5371,62 @@ subroutine real_to_string(rval,str)
5348
5371
real (RK),intent (in ) :: rval
5349
5372
character (kind= CK,len=* ),intent (out ) :: str
5350
5373
5351
- integer (IK) :: istat
5374
+ character (kind= CK,len= len (str)) :: significand, expnt
5375
+ character (kind= CK,len= 2 ) :: separator
5376
+ integer (IK) :: istat, exp_start, decimal_pos, sig_trim, exp_trim, i
5352
5377
5353
5378
write (str,fmt= real_fmt,iostat= istat) rval
5354
5379
5355
5380
if (istat== 0 ) then
5356
5381
str = adjustl (str)
5382
+ exp_start = scan (str,CK_' eEdD' )
5383
+ if (exp_start == 0 ) exp_start = scan (str,CK_' -+' ,back= .true. )
5384
+ decimal_pos = scan (str,CK_' .' )
5385
+ if (exp_start /= 0 ) separator = str(exp_start:exp_start)
5386
+ if (exp_start > 0 .and. exp_start < decimal_pos) then ! signed, exponent-less float
5387
+ significand = str
5388
+ sig_trim = len (trim (significand))
5389
+ do i = len (trim (significand)),decimal_pos+2 ,- 1 ! look from right to left at 0s
5390
+ ! but save one after the decimal place
5391
+ if (significand(i:i) == CK_' 0' ) then
5392
+ sig_trim = i-1
5393
+ else
5394
+ exit
5395
+ end if
5396
+ end do
5397
+ str = trim (significand(1 :sig_trim))
5398
+ else if (exp_start > decimal_pos) then ! float has exponent
5399
+ significand = str(1 :exp_start-1 )
5400
+ sig_trim = len (trim (significand))
5401
+ do i = len (trim (significand)),decimal_pos+2 ,- 1 ! look from right to left at 0s
5402
+ if (significand(i:i) == CK_' 0' ) then
5403
+ sig_trim = i-1
5404
+ else
5405
+ exit
5406
+ end if
5407
+ end do
5408
+ expnt = adjustl (str(exp_start+1 :))
5409
+ if (expnt(1 :1 ) == CK_' +' .or. expnt(1 :1 ) == CK_' -' ) then
5410
+ separator = trim (adjustl (separator))// expnt(1 :1 )
5411
+ exp_start = exp_start + 1
5412
+ expnt = adjustl (str(exp_start+1 :))
5413
+ end if
5414
+ exp_trim = 1
5415
+ do i = 1 ,(len (trim (expnt))- 1 ) ! look at exponent leading zeros saving last
5416
+ if (expnt(i:i) == CK_' 0' ) then
5417
+ exp_trim = i+1
5418
+ else
5419
+ exit
5420
+ end if
5421
+ end do
5422
+ str = trim (adjustl (significand(1 :sig_trim)))// &
5423
+ trim (adjustl (separator))// &
5424
+ trim (adjustl (expnt(exp_trim:)))
5425
+
5426
+ ! else ! mal-formed real, BUT this code should be unreachable
5427
+
5428
+ end if
5429
+
5357
5430
else
5358
5431
str = repeat (star,len (str))
5359
5432
end if
0 commit comments