Skip to content

Commit 8b74ef2

Browse files
committed
Fixed bug in invalid annotate routine. Added a unit test to test this. Fixes #355
Reverted an inadvertent regression in the previous commit. The arguments to json_file_check_for_errors are now optional to match the core routine. Fixes #356 Added some workaround in the error checking routine to gfortran bugs.
1 parent d4462f1 commit 8b74ef2

File tree

6 files changed

+79
-21
lines changed

6 files changed

+79
-21
lines changed

files/inputs/invalid3.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"a": "blah\",
3+
"b": 2
4+
}

files/inputs/test1.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"..\\path\\to\\files\\file3.txt",
1313
"test \u2FA4 \uABCD \uABCD\uABCDtest",
1414
" test \\u \" blah\\\" test test",
15-
"..\\path\\to\\files\\"
15+
"..\\path\\to\\files\\",
16+
"\\"
1617
],
1718
"a": {
1819
"b": 1

src/json_file_module.F90

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,17 @@ subroutine json_file_check_for_errors(me,status_ok,error_msg)
320320
implicit none
321321

322322
class(json_file),intent(inout) :: me
323-
logical(LK),intent(out) :: status_ok !! true if there were no errors
324-
character(kind=CK,len=:),allocatable,intent(out) :: error_msg !! the error message (if there were errors)
325-
323+
logical(LK),intent(out),optional :: status_ok !! true if there were no errors
324+
character(kind=CK,len=:),allocatable,intent(out),optional :: error_msg !! the error message
325+
!! (if there were errors)
326+
327+
#if defined __GFORTRAN__
328+
character(kind=CK,len=:),allocatable :: tmp !! workaround for gfortran bugs
329+
call me%core%check_for_errors(status_ok,tmp)
330+
error_msg = tmp
331+
#else
326332
call me%core%check_for_errors(status_ok,error_msg)
333+
#endif
327334

328335
end subroutine json_file_check_for_errors
329336
!*****************************************************************************************

src/json_value_module.F90

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,7 +1917,7 @@ end subroutine wrap_json_throw_exception
19171917
! * [[json_failed]]
19181918
! * [[json_throw_exception]]
19191919

1920-
pure subroutine json_check_for_errors(json,status_ok,error_msg)
1920+
subroutine json_check_for_errors(json,status_ok,error_msg)
19211921

19221922
implicit none
19231923

@@ -1927,14 +1927,23 @@ pure subroutine json_check_for_errors(json,status_ok,error_msg)
19271927
!! (not allocated if
19281928
!! there were no errors)
19291929

1930+
#if defined __GFORTRAN__
1931+
character(kind=CK,len=:),allocatable :: tmp !! workaround for gfortran bugs
1932+
#endif
1933+
19301934
if (present(status_ok)) status_ok = .not. json%exception_thrown
19311935

19321936
if (present(error_msg)) then
19331937
if (json%exception_thrown) then
19341938
! if an exception has been thrown,
19351939
! then this will always be allocated
19361940
! [see json_throw_exception]
1941+
#if defined __GFORTRAN__
1942+
tmp = json%err_message
1943+
error_msg = tmp
1944+
#else
19371945
error_msg = json%err_message
1946+
#endif
19381947
end if
19391948
end if
19401949

@@ -8752,12 +8761,9 @@ subroutine json_parse_file(json, file, p, unit)
87528761
! but we'll allocate something here just in case.
87538762
p%name = trim(file) !use the file name
87548763

8755-
! parse as a value
8764+
! parse as a value
87568765
call json%parse_value(unit=iunit, str=CK_'', value=p)
87578766

8758-
! close the file if necessary
8759-
close(unit=iunit, iostat=istat)
8760-
87618767
! check for errors:
87628768
if (json%exception_thrown) then
87638769
call json%annotate_invalid_json(iunit,CK_'')
@@ -8773,6 +8779,9 @@ subroutine json_parse_file(json, file, p, unit)
87738779
end if
87748780
end if
87758781

8782+
! close the file:
8783+
close(unit=iunit, iostat=istat)
8784+
87768785
else
87778786

87788787
call json%throw_exception('Error in json_parse_file: Error opening file: '//trim(file))
@@ -8872,8 +8881,8 @@ subroutine annotate_invalid_json(json,iunit,str)
88728881
integer(IK) :: i_nl_prev !! index of previous newline character
88738882
integer(IK) :: i_nl !! index of current newline character
88748883

8875-
! If there was an error reading the file, then
8876-
! print the line where the error occurred:
8884+
! If there was an error reading the file, then
8885+
! print the line where the error occurred:
88778886
if (json%exception_thrown) then
88788887

88798888
!the counters for the current line and the last character read:
@@ -8918,8 +8927,13 @@ subroutine annotate_invalid_json(json,iunit,str)
89188927
end if
89198928

89208929
!create the error message:
8921-
if (allocated(json%err_message)) json%err_message = json%err_message//newline
8922-
json%err_message = 'line: '//trim(adjustl(line_str))//', '//&
8930+
if (allocated(json%err_message)) then
8931+
json%err_message = json%err_message//newline
8932+
else
8933+
json%err_message = ''
8934+
end if
8935+
json%err_message = json%err_message//&
8936+
'line: '//trim(adjustl(line_str))//', '//&
89238937
'character: '//trim(adjustl(char_str))//newline//&
89248938
trim(line)//newline//arrow_str
89258939

@@ -9883,6 +9897,7 @@ subroutine parse_string(json, unit, str, string)
98839897
!! if necessary)
98849898

98859899
logical(LK) :: eof !! end of file flag
9900+
logical(LK) :: escape !! for escape string parsing
98869901
character(kind=CK,len=1) :: c !! character returned by [[pop_char]]
98879902
integer(IK) :: ip !! index to put next character,
98889903
!! to speed up by reducing the number
@@ -9895,7 +9910,8 @@ subroutine parse_string(json, unit, str, string)
98959910
if (.not. json%exception_thrown) then
98969911

98979912
!initialize:
9898-
ip = 1
9913+
escape = .false.
9914+
ip = 1
98999915

99009916
do
99019917

@@ -9907,7 +9923,7 @@ subroutine parse_string(json, unit, str, string)
99079923
call json%throw_exception('Error in parse_string: Expecting end of string')
99089924
return
99099925

9910-
else if (c==quotation_mark) then !end of string
9926+
else if (c==quotation_mark .and. .not. escape) then !end of string
99119927

99129928
exit
99139929

@@ -9920,6 +9936,15 @@ subroutine parse_string(json, unit, str, string)
99209936
string(ip:ip) = c
99219937
ip = ip + 1
99229938

9939+
! check for escape character, so we don't
9940+
! exit prematurely if escaping a quotation
9941+
! character:
9942+
if (escape) then
9943+
escape = .false.
9944+
else
9945+
escape = (c==backslash)
9946+
end if
9947+
99239948
end if
99249949

99259950
end do

src/tests/jf_test_06.F90

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
module jf_test_6_mod
99

10-
use json_module
10+
use json_module, CK => json_CK, LK => json_LK
11+
use json_parameters, only: newline
1112
use, intrinsic :: iso_fortran_env , only: error_unit, output_unit, wp => real64
1213

1314
implicit none
@@ -29,9 +30,12 @@ subroutine test_6(error_cnt)
2930

3031
type(json_file) :: json
3132
integer :: i
33+
character(kind=CK,len=:),allocatable :: error_msg
34+
logical(LK) :: status_ok
3235

33-
character(len=*),dimension(2),parameter :: files = ['invalid.json ',&
34-
'invalid2.json']
36+
character(len=*),dimension(3),parameter :: files = ['invalid.json ',&
37+
'invalid2.json',&
38+
'invalid3.json']
3539

3640
error_cnt = 0
3741
call json%initialize()
@@ -46,15 +50,32 @@ subroutine test_6(error_cnt)
4650
write(error_unit,'(A)') '================================='
4751
write(error_unit,'(A)') ''
4852

49-
do i=1,2
53+
do i=1,size(files)
5054

5155
! parse the json file:
5256
write(error_unit,'(A)') ''
5357
write(error_unit,'(A)') 'load file: '//trim(files(i))
5458
write(error_unit,'(A)') ''
5559
call json%load_file(filename = dir//trim(files(i)))
5660
if (json%failed()) then
61+
62+
if (i==1) then
63+
call json%check_for_errors(status_ok, error_msg=error_msg)
64+
65+
if (error_msg /= &
66+
CK_'Error in parse_array: Unexpected character encountered when parsing array.'//newline//&
67+
CK_'line: 13, character: 1'//newline//&
68+
CK_'}'//newline//&
69+
''//newline//&
70+
'^') then
71+
! verify that the expected error string is present
72+
write(error_unit,'(A)') 'Error: unexpected error message string: "'//error_msg//'"'
73+
error_cnt = error_cnt + 1
74+
end if
75+
end if
76+
5777
call json%print_error_message(error_unit)
78+
5879
else
5980
write(error_unit,'(A)') 'An error should have been raised!'
6081
error_cnt = error_cnt + 1

src/tests/jf_test_10.F90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ subroutine test_10(error_cnt)
144144
error_cnt = error_cnt + 1
145145
else
146146
!also make sure the values are correct:
147-
if (found .and. size(str_vec)==6 .and. &
147+
if (found .and. size(str_vec)==7 .and. &
148148
str_vec(1)=='..\path\to\files\file1.txt') then
149149
write(error_unit,'(A)') '...success'
150150
else
@@ -303,7 +303,7 @@ subroutine test_10(error_cnt)
303303
error_cnt = error_cnt + 1
304304
else
305305
!also make sure the values are correct:
306-
if (found .and. size(str_vec)==6 .and. &
306+
if (found .and. size(str_vec)==7 .and. &
307307
str_vec(1)=='..\path\to\files\file1.txt') then
308308
write(error_unit,'(A)') '...success'
309309
else

0 commit comments

Comments
 (0)