Get the next character from the file (or string).
Note
This routine ignores non-printing ASCII characters
(iachar<=31
) that are in strings.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(json_core), | intent(inout) | :: | json | |||
integer(kind=IK), | intent(in) | :: | unit |
file unit number (if parsing from a file) |
||
character(kind=CK, len=*), | intent(in) | :: | str |
JSON string (if parsing from a
string) – only used if |
||
logical(kind=LK), | intent(in), | optional | :: | skip_ws |
to ignore whitespace [default False] |
|
logical(kind=LK), | intent(in), | optional | :: | skip_comments |
to ignore comment lines [default False] |
|
logical(kind=LK), | intent(out) | :: | eof |
true if the end of the file has been reached. |
||
character(kind=CK, len=1), | intent(out) | :: | popped |
the popped character returned |
subroutine pop_char(json,unit,str,skip_ws,skip_comments,eof,popped) implicit none class(json_core),intent(inout) :: json integer(IK),intent(in) :: unit !! file unit number (if parsing !! from a file) character(kind=CK,len=*),intent(in) :: str !! JSON string (if parsing from a !! string) -- only used if `unit=0` logical(LK),intent(in),optional :: skip_ws !! to ignore whitespace [default False] logical(LK),intent(in),optional :: skip_comments !! to ignore comment lines [default False] logical(LK),intent(out) :: eof !! true if the end of the file has !! been reached. character(kind=CK,len=1),intent(out) :: popped !! the popped character returned integer(IK) :: ios !! `iostat` flag integer(IK) :: str_len !! length of `str` character(kind=CK,len=1) :: c !! a character read from the file (or string) logical(LK) :: ignore !! if whitespace is to be ignored logical(LK) :: ignore_comments !! if comment lines are to be ignored logical(LK) :: parsing_comment !! if we are in the process !! of parsing a comment line if (.not. json%exception_thrown) then eof = .false. if (.not. present(skip_ws)) then ignore = .false. else ignore = skip_ws end if parsing_comment = .false. if (.not. present(skip_comments)) then ignore_comments = .false. else ignore_comments = skip_comments end if do if (json%pushed_index > 0) then ! there is a character pushed back on, most likely ! from the number parsing. Note: this can only occur if ! reading from a file when use_unformatted_stream=.false. c = json%pushed_char(json%pushed_index:json%pushed_index) json%pushed_index = json%pushed_index - 1 else if (unit/=0) then !read from the file !read the next character: if (use_unformatted_stream) then ! in this case, we read the file in chunks. ! if we already have the character we need, ! then get it from the chunk. Otherwise, ! read in another chunk. if (json%ichunk<1) then ! read in a chunk: json%ichunk = 0 if (json%filesize<json%ipos+len(json%chunk)-1) then ! for the last chunk, we resize ! it to the correct size: json%chunk = repeat(space, json%filesize-json%ipos+1) end if read(unit=unit,pos=json%ipos,iostat=ios) json%chunk else ios = 0 end if json%ichunk = json%ichunk + 1 if (json%ichunk>len(json%chunk)) then ! check this just in case ios = IOSTAT_END else ! get the next character from the chunk: c = json%chunk(json%ichunk:json%ichunk) if (json%ichunk==len(json%chunk)) then json%ichunk = 0 ! reset for next chunk end if end if else ! a formatted read: read(unit=unit,fmt='(A1)',advance='NO',iostat=ios) c end if json%ipos = json%ipos + 1 else !read from the string str_len = len(str) !length of the string if (json%ipos<=str_len) then c = str(json%ipos:json%ipos) ios = 0 else ios = IOSTAT_END !end of the string end if json%ipos = json%ipos + 1 end if json%char_count = json%char_count + 1 !character count in the current line if (IS_IOSTAT_END(ios)) then !end of file ! no character to return json%char_count = 0 eof = .true. popped = space ! just to set a value exit else if (IS_IOSTAT_EOR(ios) .or. c==newline) then !end of record json%char_count = 0 json%line_count = json%line_count + 1 if (ignore_comments) parsing_comment = .false. ! done parsing this comment line cycle end if end if if (ignore_comments .and. (parsing_comment .or. scan(c,json%comment_char,kind=IK)>0_IK) ) then ! skipping the comment parsing_comment = .true. cycle else if (any(c == control_chars)) then ! non printing ascii characters cycle else if (ignore .and. c == space) then ! ignoring whitespace cycle else ! return the character popped = c exit end if end do end if end subroutine pop_char