@@ -256,6 +256,12 @@ module json_value_module
256
256
! ! (both escaped and unescaped versions are still
257
257
! ! valid in all cases).
258
258
259
+ integer :: ichunk = 0 ! ! index in `chunk` for [[pop_char]]
260
+ ! ! when `use_unformatted_stream=True`
261
+ integer :: filesize = 0 ! ! the file size when when `use_unformatted_stream=True`
262
+ character (kind= CK,len= :),allocatable :: chunk ! ! a chunk read from a stream file
263
+ ! ! when `use_unformatted_stream=True`
264
+
259
265
contains
260
266
261
267
private
@@ -918,6 +924,11 @@ subroutine json_initialize(me,verbose,compact_reals,&
918
924
me% char_count = 0
919
925
me% line_count = 1
920
926
me% ipos = 1
927
+ if (use_unformatted_stream) then
928
+ me% filesize = 0
929
+ me% ichunk = 0
930
+ me% chunk = repeat (' ' , stream_chunk_size) ! default chunk size
931
+ end if
921
932
922
933
#ifdef USE_UCS4
923
934
! reopen stdout and stderr with utf-8 encoding
@@ -8755,6 +8766,11 @@ subroutine json_parse_file(json, file, p, unit)
8755
8766
8756
8767
if (istat== 0 ) then
8757
8768
8769
+ if (use_unformatted_stream) then
8770
+ ! save the file save to be read:
8771
+ inquire (unit= iunit, size= json% filesize, iostat= istat)
8772
+ end if
8773
+
8758
8774
! create the value and associate the pointer
8759
8775
call json_value_create(p)
8760
8776
@@ -9110,6 +9126,7 @@ recursive subroutine parse_value(json, unit, str, value)
9110
9126
! the routine is being called incorrectly.
9111
9127
if (.not. associated (value)) then
9112
9128
call json% throw_exception(' Error in parse_value: value pointer not associated.' )
9129
+ return
9113
9130
end if
9114
9131
9115
9132
! pop the next non whitespace character off the file
@@ -9957,7 +9974,7 @@ subroutine parse_string(json, unit, str, string)
9957
9974
character (kind= CK,len= :),allocatable :: error_message ! ! for string unescaping
9958
9975
9959
9976
! at least return a blank string if there is a problem:
9960
- string = repeat (space, chunk_size)
9977
+ string = blank_chunk
9961
9978
9962
9979
if (.not. json% exception_thrown) then
9963
9980
@@ -9982,7 +9999,7 @@ subroutine parse_string(json, unit, str, string)
9982
9999
else
9983
10000
9984
10001
! if the string is not big enough, then add another chunk:
9985
- if (ip> len (string)) string = string // repeat (space, chunk_size)
10002
+ if (ip> len (string)) string = string // blank_chunk
9986
10003
9987
10004
! append to string:
9988
10005
string (ip:ip) = c
@@ -10098,7 +10115,7 @@ subroutine parse_number(json, unit, str, value)
10098
10115
10099
10116
if (.not. json% exception_thrown) then
10100
10117
10101
- tmp = repeat (space, chunk_size)
10118
+ tmp = blank_chunk
10102
10119
ip = 1
10103
10120
first = .true.
10104
10121
is_integer = .true. ! assume it may be an integer, unless otherwise determined
@@ -10122,7 +10139,7 @@ subroutine parse_number(json, unit, str, value)
10122
10139
10123
10140
! add it to the string:
10124
10141
! tmp = tmp // c !...original
10125
- if (ip> len (tmp)) tmp = tmp // repeat (space, chunk_size)
10142
+ if (ip> len (tmp)) tmp = tmp // blank_chunk
10126
10143
tmp(ip:ip) = c
10127
10144
ip = ip + 1
10128
10145
@@ -10132,15 +10149,15 @@ subroutine parse_number(json, unit, str, value)
10132
10149
10133
10150
! add it to the string:
10134
10151
! tmp = tmp // c !...original
10135
- if (ip> len (tmp)) tmp = tmp // repeat (space, chunk_size)
10152
+ if (ip> len (tmp)) tmp = tmp // blank_chunk
10136
10153
tmp(ip:ip) = c
10137
10154
ip = ip + 1
10138
10155
10139
10156
case (CK_' 0' :CK_' 9' ) ! valid characters for numbers
10140
10157
10141
10158
! add it to the string:
10142
10159
! tmp = tmp // c !...original
10143
- if (ip> len (tmp)) tmp = tmp // repeat (space, chunk_size)
10160
+ if (ip> len (tmp)) tmp = tmp // blank_chunk
10144
10161
tmp(ip:ip) = c
10145
10162
ip = ip + 1
10146
10163
@@ -10185,7 +10202,7 @@ end subroutine parse_number
10185
10202
! @note This routine ignores non-printing ASCII characters
10186
10203
! (`iachar<=31`) that are in strings.
10187
10204
10188
- recursive subroutine pop_char (json ,unit ,str ,skip_ws ,skip_comments ,eof ,popped )
10205
+ subroutine pop_char (json ,unit ,str ,skip_ws ,skip_comments ,eof ,popped )
10189
10206
10190
10207
implicit none
10191
10208
@@ -10239,16 +10256,41 @@ recursive subroutine pop_char(json,unit,str,skip_ws,skip_comments,eof,popped)
10239
10256
10240
10257
! read the next character:
10241
10258
if (use_unformatted_stream) then
10242
- read (unit= unit,pos= json% ipos,iostat= ios) c
10259
+
10260
+ ! in this case, we read the file in chunks.
10261
+ ! if we already have the character we need,
10262
+ ! then get it from the chunk. Otherwise,
10263
+ ! read in another chunk.
10264
+ if (json% ichunk< 1 ) then
10265
+ ! read in a chunk:
10266
+ json% ichunk = 0
10267
+ if (json% filesize< json% ipos+ len (json% chunk)- 1 ) then
10268
+ ! for the last chunk, we resize
10269
+ ! it to the correct size:
10270
+ json% chunk = repeat (' ' , json% filesize- json% ipos+1 )
10271
+ end if
10272
+ read (unit= unit,pos= json% ipos,iostat= ios) json% chunk
10273
+ else
10274
+ ios = 0
10275
+ end if
10276
+ json% ichunk = json% ichunk + 1
10277
+ if (json% ichunk> len (json% chunk)) then
10278
+ ! check this just in case
10279
+ ios = IOSTAT_END
10280
+ else
10281
+ ! get the next character from the chunk:
10282
+ c = json% chunk(json% ichunk:json% ichunk)
10283
+ if (json% ichunk== len (json% chunk)) then
10284
+ json% ichunk = 0 ! reset for next chunk
10285
+ end if
10286
+ end if
10287
+
10243
10288
else
10289
+ ! a formatted read:
10244
10290
read (unit= unit,fmt= ' (A1)' ,advance= ' NO' ,iostat= ios) c
10245
10291
end if
10246
10292
json% ipos = json% ipos + 1
10247
10293
10248
- ! ....note: maybe try read the file in chunks...
10249
- ! .... or use asynchronous read with double buffering
10250
- ! (see Modern Fortran: Style and Usage)
10251
-
10252
10294
else ! read from the string
10253
10295
10254
10296
str_len = len (str) ! length of the string
@@ -10339,7 +10381,8 @@ subroutine push_char(json,c)
10339
10381
10340
10382
! in this case, c is ignored, and we just
10341
10383
! decrement the stream position counter:
10342
- json% ipos = json% ipos - 1
10384
+ json% ipos = json% ipos - 1
10385
+ json% ichunk = json% ichunk - 1
10343
10386
10344
10387
else
10345
10388
0 commit comments