Skip to content

Commit

Permalink
Refactored the parse_array routine.
Browse files Browse the repository at this point in the history
-no longer recursive.
-added additional error exceptions during parsing if the file is invalid (included a new test case for this).
added a new verbose error printing mode.
  • Loading branch information
jacobwilliams committed Dec 27, 2014
1 parent a9f690e commit e636f96
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 20 deletions.
13 changes: 13 additions & 0 deletions files/invalid.json
@@ -0,0 +1,13 @@
{
"notes": "This is an invalid JSON file, used to test error handling.",
"version": {
"major": 2,
"minor": 0,
"patch": 0,
"revision": 1805
},
"files": [
"..\\path\\to\\files\\file1.txt",
"..\\path\\to\\files\\file2.txt",
"..\\path\\to\\files\\file3.txt"
}
33 changes: 33 additions & 0 deletions src/json_example.f90
Expand Up @@ -70,12 +70,45 @@ program json_test
call test_3()
call test_4()
call test_5()
call test_6()

!call memory_leak_test()

contains
!*******************************************************************************************************


!**************************************************************
subroutine test_6()
!**************************************************************
!
! This example tries to read an invalid json file.
!
!**************************************************************
implicit none

type(json_file) :: json

write(*,'(A)') ''
write(*,'(A)') '================================='
write(*,'(A)') ' EXAMPLE 6 : invalid JSON file '
write(*,'(A)') '================================='
write(*,'(A)') ''

! parse the json file:
write(*,'(A)') 'load file...'
call json%load_file(filename = dir//'invalid.json')
if (json_failed()) then
call print_error_message()
end if

! clean up
call json%destroy()

!**************************************************************
end subroutine test_6
!**************************************************************

!**************************************************************
subroutine test_5()
!**************************************************************
Expand Down
57 changes: 37 additions & 20 deletions src/json_module.f90
Expand Up @@ -465,8 +465,9 @@ end subroutine array_callback_func
public :: to_array !

!exception handling [private variables]
logical :: exception_thrown = .false. !the error flag
character(len=:),allocatable :: err_message !the error message
logical :: is_verbose = .false. !if true, all exceptions are immediately printed to console
logical :: exception_thrown = .false. !the error flag
character(len=:),allocatable :: err_message !the error message

! POP/PUSH CHARACTER [private variables]
integer :: char_count = 0
Expand Down Expand Up @@ -1030,9 +1031,14 @@ end subroutine get_char_vec_from_json_file
!
! SOURCE

subroutine json_initialize()
subroutine json_initialize(verbose)

implicit none

logical,intent(in),optional :: verbose !mainly useful for debugging (default is false)

!optional input (if not present, value remains unchanged):
if (present(verbose)) is_verbose = verbose

!clear any errors from previous runs:
call json_clear_exceptions()
Expand Down Expand Up @@ -1095,7 +1101,13 @@ subroutine throw_exception(msg)

exception_thrown = .true.
err_message = trim(msg)


if (is_verbose) then
write(*,'(A)') '***********************'
write(*,'(A)') 'JSON-FORTRAN EXCEPTION: '//trim(msg)
write(*,'(A)') '***********************'
end if

end subroutine throw_exception
!*****************************************************************************************

Expand Down Expand Up @@ -4165,11 +4177,11 @@ end subroutine parse_object
! parse_array
!
! DESCRIPTION
!
! Core parsing routine.
!
! SOURCE

recursive subroutine parse_array(unit, array)
subroutine parse_array(unit, array)

This comment has been minimized.

Copy link
@zbeekman

zbeekman Dec 30, 2014

Contributor

It looks like this is where #28 was introduced… Is my understanding correct?


implicit none

Expand All @@ -4179,36 +4191,41 @@ recursive subroutine parse_array(unit, array)
type(json_value), pointer :: element
logical :: eof
character(len=1) :: c

do

if (.not. exception_thrown) then
nullify(element)
if (exception_thrown) exit

! try to parse an element value
nullify(element)
call json_value_create(element)
call parse_value(unit, element)
if (exception_thrown) return
if (exception_thrown) exit

! parse value will disassociate an empty array value
if (associated(element)) then
call json_value_add(array, element)
nullify(element) !cleanup
end if
if (associated(element)) call json_value_add(array, element)

! popped the next character
c = pop_char(unit, eof = eof, skip_ws = .true.)

if (eof) then
return
! The file ended before array was finished:
call throw_exception('Error in parse_array: '//&
'End of file encountered when parsing an array.')
exit
else if (',' == c) then
! parse the next element
call parse_array(unit, array)
if (exception_thrown) return
cycle
else if (']' == c) then
! end of array
return
exit
else
call throw_exception('Error in parse_array: '//&
'Unexpected character encountered when parsing array.')
exit
end if

end if
end do

end subroutine parse_array
!*****************************************************************************************
Expand Down Expand Up @@ -4320,7 +4337,7 @@ end subroutine parse_string
! parse_for_chars
!
! DESCRIPTION
!
! Core parsing routine.
!
! SOURCE

Expand Down

1 comment on commit e636f96

@zbeekman
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that this commit introduces backwards-compatible additional functionality, which, according to semantic versioning, requires a bump in the minor version number…

Please sign in to comment.