Parses a string while reading a JSON file.
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) |
||
character(kind=CK,len=:), | intent(out), | allocatable | :: | string |
subroutine parse_string(json, unit, str, string)
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)
character(kind=CK,len=:),allocatable,intent(out) :: string
logical(LK) :: eof, is_hex, escape
character(kind=CK,len=1) :: c
character(kind=CK,len=4) :: hex
integer(IK) :: i
integer(IK) :: ip !! index to put next character,
!! to speed up by reducing the number of character string reallocations.
!at least return a blank string if there is a problem:
string = repeat(space, chunk_size)
if (.not. json%exception_thrown) then
!initialize:
ip = 1
is_hex = .false.
escape = .false.
i = 0
do
!get the next character from the file:
call json%pop_char(unit, str=str, eof=eof, skip_ws=.false., popped=c)
if (eof) then
call json%throw_exception('Error in parse_string: Expecting end of string')
return
else if (c==quotation_mark .and. .not. escape) then !end of string
if (is_hex) call json%throw_exception('Error in parse_string:'//&
' incomplete hex string: \u'//trim(hex))
exit
else
!if the string is not big enough, then add another chunk:
if (ip>len(string)) string = string // repeat(space, chunk_size)
!append to string:
string(ip:ip) = c
ip = ip + 1
!hex validation:
if (is_hex) then !accumulate the four characters after '\u'
i=i+1
hex(i:i) = c
if (i==4) then
if (valid_json_hex(hex)) then
i = 0
hex = CK_''
is_hex = .false.
else
call json%throw_exception('Error in parse_string:'//&
' invalid hex string: \u'//trim(hex))
exit
end if
end if
else
!when the '\u' string is encountered, then
! start accumulating the hex string (should be the next 4 characters)
if (escape) then
escape = .false.
is_hex = (c=='u') !the next four characters are the hex string
else
escape = (c==backslash)
end if
end if
end if
end do
!trim the string if necessary:
if (ip<len(string)+1) then
if (ip==1) then
string = CK_''
else
string = string(1:ip-1)
end if
end if
end if
end subroutine parse_string