@@ -256,6 +256,11 @@ 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
+ character (kind= CK,len= stream_chunk_size) :: chunk = CK_' ' ! ! a chunk read from a stream file
262
+ ! ! when `use_unformatted_stream=True`
263
+
259
264
contains
260
265
261
266
private
@@ -917,6 +922,8 @@ subroutine json_initialize(me,verbose,compact_reals,&
917
922
me% char_count = 0
918
923
me% line_count = 1
919
924
me% ipos = 1
925
+ me% ichunk = 0
926
+ me% chunk = ' '
920
927
921
928
#ifdef USE_UCS4
922
929
! reopen stdout and stderr with utf-8 encoding
@@ -10147,7 +10154,7 @@ end subroutine parse_number
10147
10154
! @note This routine ignores non-printing ASCII characters
10148
10155
! (`iachar<=31`) that are in strings.
10149
10156
10150
- recursive subroutine pop_char (json ,unit ,str ,skip_ws ,skip_comments ,eof ,popped )
10157
+ subroutine pop_char (json ,unit ,str ,skip_ws ,skip_comments ,eof ,popped )
10151
10158
10152
10159
implicit none
10153
10160
@@ -10170,6 +10177,10 @@ recursive subroutine pop_char(json,unit,str,skip_ws,skip_comments,eof,popped)
10170
10177
logical (LK) :: parsing_comment ! ! if we are in the process
10171
10178
! ! of parsing a comment line
10172
10179
10180
+ logical ,parameter :: chunk_it = .true. ! ! if true, stream files are read in chunks,
10181
+ ! ! rather than one character at a time.
10182
+ ! ! this speeds up the parsing dramatically.
10183
+
10173
10184
if (.not. json% exception_thrown) then
10174
10185
10175
10186
eof = .false.
@@ -10201,16 +10212,37 @@ recursive subroutine pop_char(json,unit,str,skip_ws,skip_comments,eof,popped)
10201
10212
10202
10213
! read the next character:
10203
10214
if (use_unformatted_stream) then
10204
- read (unit= unit,pos= json% ipos,iostat= ios) c
10215
+
10216
+ if (chunk_it) then
10217
+ ! in this case, we read the file in chunks.
10218
+ ! if we already have the character we need,
10219
+ ! then get it from the chunk. Otherwise,
10220
+ ! read another chunk
10221
+
10222
+ if (json% ichunk< 1 ) then
10223
+ json% ichunk = 0
10224
+ read (unit= unit,pos= json% ipos,iostat= ios) json% chunk
10225
+ else
10226
+ ios = 0
10227
+ end if
10228
+ json% ichunk = json% ichunk + 1
10229
+ c = json% chunk(json% ichunk:json% ichunk)
10230
+ if (json% ichunk== len (json% chunk)) then
10231
+ json% ichunk = 0 ! reset
10232
+ else
10233
+ ! we have to finish getting
10234
+ ! characters from this chunk:
10235
+ if (IS_IOSTAT_END(ios)) ios = 0
10236
+ end if
10237
+ else
10238
+ read (unit= unit,pos= json% ipos,iostat= ios) c
10239
+ end if
10240
+
10205
10241
else
10206
10242
read (unit= unit,fmt= ' (A1)' ,advance= ' NO' ,iostat= ios) c
10207
10243
end if
10208
10244
json% ipos = json% ipos + 1
10209
10245
10210
- ! ....note: maybe try read the file in chunks...
10211
- ! .... or use asynchronous read with double buffering
10212
- ! (see Modern Fortran: Style and Usage)
10213
-
10214
10246
else ! read from the string
10215
10247
10216
10248
str_len = len (str) ! length of the string
@@ -10302,6 +10334,7 @@ subroutine push_char(json,c)
10302
10334
! in this case, c is ignored, and we just
10303
10335
! decrement the stream position counter:
10304
10336
json% ipos = json% ipos - 1
10337
+ json% ichunk = json% ichunk - 1
10305
10338
10306
10339
else
10307
10340
0 commit comments