Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
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 |
Parses a string while reading a JSON file.
Type | Visibility | Attributes | Name | Initial | |||
---|---|---|---|---|---|---|---|
logical(kind=LK), | public | :: | eof | ||||
logical(kind=LK), | public | :: | is_hex | ||||
logical(kind=LK), | public | :: | escape | ||||
character(kind=CK,len=1), | public | :: | c | ||||
character(kind=CK,len=4), | public | :: | hex | ||||
integer(kind=IK), | public | :: | i | ||||
integer(kind=IK), | public | :: | ip | index to put next character, to speed up by reducing the number of character string reallocations. |
subroutine parse_string(unit, str, string)
implicit none
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. exception_thrown) then
!initialize:
ip = 1
is_hex = .false.
escape = .false.
i = 0
do
!get the next character from the file:
c = pop_char(unit, str=str, eof = eof, skip_ws = .false.)
if (eof) then
call 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 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 = ''
is_hex = .false.
else
call 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 = ''
else
string = string(1:ip-1)
end if
end if
end if
end subroutine parse_string