@@ -256,6 +256,11 @@ module json_value_module
256256 ! ! (both escaped and unescaped versions are still
257257 ! ! valid in all cases).
258258
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+
259264 contains
260265
261266 private
@@ -917,6 +922,8 @@ subroutine json_initialize(me,verbose,compact_reals,&
917922 me% char_count = 0
918923 me% line_count = 1
919924 me% ipos = 1
925+ me% ichunk = 0
926+ me% chunk = ' '
920927
921928#ifdef USE_UCS4
922929 ! reopen stdout and stderr with utf-8 encoding
@@ -10147,7 +10154,7 @@ end subroutine parse_number
1014710154! @note This routine ignores non-printing ASCII characters
1014810155! (`iachar<=31`) that are in strings.
1014910156
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 )
1015110158
1015210159 implicit none
1015310160
@@ -10170,6 +10177,10 @@ recursive subroutine pop_char(json,unit,str,skip_ws,skip_comments,eof,popped)
1017010177 logical (LK) :: parsing_comment ! ! if we are in the process
1017110178 ! ! of parsing a comment line
1017210179
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+
1017310184 if (.not. json% exception_thrown) then
1017410185
1017510186 eof = .false.
@@ -10201,16 +10212,37 @@ recursive subroutine pop_char(json,unit,str,skip_ws,skip_comments,eof,popped)
1020110212
1020210213 ! read the next character:
1020310214 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+
1020510241 else
1020610242 read (unit= unit,fmt= ' (A1)' ,advance= ' NO' ,iostat= ios) c
1020710243 end if
1020810244 json% ipos = json% ipos + 1
1020910245
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-
1021410246 else ! read from the string
1021510247
1021610248 str_len = len (str) ! length of the string
@@ -10302,6 +10334,7 @@ subroutine push_char(json,c)
1030210334 ! in this case, c is ignored, and we just
1030310335 ! decrement the stream position counter:
1030410336 json% ipos = json% ipos - 1
10337+ json% ichunk = json% ichunk - 1
1030510338
1030610339 else
1030710340
0 commit comments