From 967cfeed179291395bd2b2c182fbd1df73a8d745 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Fri, 20 Jul 2018 16:50:30 -0500 Subject: [PATCH 01/10] Some efficiency improvements when parsing strings. Fixes #351 --- src/json_file_module.F90 | 3 +- src/json_string_utilities.F90 | 66 +++++++++++++++-------------------- src/json_value_module.F90 | 12 ++----- 3 files changed, 34 insertions(+), 47 deletions(-) diff --git a/src/json_file_module.F90 b/src/json_file_module.F90 index cc62dbb320..6f5ffd9fc6 100644 --- a/src/json_file_module.F90 +++ b/src/json_file_module.F90 @@ -64,7 +64,8 @@ module json_file_module private - type(json_core) :: core !! The instance of the [[json_core(type)]] factory used for this file. + type(json_core) :: core !! The instance of the [[json_core(type)]] + !! factory used for this file. type(json_value),pointer :: p => null() !! the JSON structure read from the file contains diff --git a/src/json_string_utilities.F90 b/src/json_string_utilities.F90 index e0c52b168a..ee9f4614ed 100644 --- a/src/json_string_utilities.F90 +++ b/src/json_string_utilities.F90 @@ -433,44 +433,45 @@ end subroutine escape_string ! * `\t` - horizontal tab ! * `\uXXXX` - 4 hexadecimal digits - subroutine unescape_string(str_in, str_out, error_message) + subroutine unescape_string(str, error_message) implicit none - character(kind=CK,len=*),intent(in) :: str_in !! string as stored in a [[json_value]] - character(kind=CK,len=:),allocatable,intent(out) :: str_out !! decoded string - character(kind=CK,len=:),allocatable,intent(out) :: error_message !! will be allocated if there was an error + character(kind=CK,len=:),allocatable,intent(inout) :: str !! in: string as stored + !! in a [[json_value]]. + !! out: decoded string. + character(kind=CK,len=:),allocatable,intent(out) :: error_message !! will be allocated if + !! there was an error integer :: i !! counter - integer :: n !! length of str_in - integer :: m !! length of str_out + integer :: n !! length of `str` + integer :: m !! length of `str_tmp` character(kind=CK,len=1) :: c !! for scanning each character in string + character(kind=CK,len=:),allocatable :: str_tmp !! temp decoded string (if the input + !! string contains an escape character + !! and needs to be decoded). -#if defined __GFORTRAN__ - character(kind=CK,len=:),allocatable :: tmp !! for GFortran bug workaround -#endif - - if (scan(str_in,backslash)>0) then + if (scan(str,backslash)>0) then !there is at least one escape character, so process this string: - n = len(str_in) - str_out = repeat(space,n) !size the output string (will be trimmed later) - m = 0 !counter in str_out - i = 0 !counter in str_in + n = len(str) + str_tmp = repeat(space,n) !size the output string (will be trimmed later) + m = 0 !counter in str_tmp + i = 0 !counter in str do i = i + 1 if (i>n) exit ! finished - c = str_in(i:i) ! get next character in the string + c = str(i:i) ! get next character in the string if (c == backslash) then if (i Date: Sat, 21 Jul 2018 09:30:47 -0500 Subject: [PATCH 02/10] some cleanup and possible efficiency improvements for hex string validation. Some adjustments to error messages for invalid hex. Fixes #354 An exception is now raised for a string that ends in an escape character. Fixes #353 --- src/json_string_utilities.F90 | 85 +++++++++++++++++++++-------------- src/json_value_module.F90 | 62 ++++++------------------- 2 files changed, 66 insertions(+), 81 deletions(-) diff --git a/src/json_string_utilities.F90 b/src/json_string_utilities.F90 index ee9f4614ed..2c7423fb9f 100644 --- a/src/json_string_utilities.F90 +++ b/src/json_string_utilities.F90 @@ -473,29 +473,34 @@ subroutine unescape_string(str, error_message) i = i + 1 c = str(i:i) !character after the escape - if (any(c == [quotation_mark,backslash,slash, & - to_unicode(['b','f','n','r','t'])])) then - - select case(c) - case (quotation_mark,backslash,slash) - !use d as is - case (CK_'b') - c = bspace - case (CK_'f') - c = formfeed - case (CK_'n') - c = newline - case (CK_'r') - c = carriage_return - case (CK_'t') - c = horizontal_tab - end select - + select case(c) + case (quotation_mark,backslash,slash) + !use d as is + m = m + 1 + str_tmp(m:m) = c + case (CK_'b') + c = bspace + m = m + 1 + str_tmp(m:m) = c + case (CK_'f') + c = formfeed + m = m + 1 + str_tmp(m:m) = c + case (CK_'n') + c = newline + m = m + 1 + str_tmp(m:m) = c + case (CK_'r') + c = carriage_return + m = m + 1 + str_tmp(m:m) = c + case (CK_'t') + c = horizontal_tab m = m + 1 str_tmp(m:m) = c - else if (c == 'u') then !expecting 4 hexadecimal digits after - !the escape character [\uXXXX] + case (CK_'u') ! expecting 4 hexadecimal digits after + ! the escape character [\uXXXX] !for now, we are just returning them as is ![not checking to see if it is a valid hex value] @@ -505,33 +510,47 @@ subroutine unescape_string(str, error_message) ! \uXXXX if (i+4<=n) then - m = m + 1 - str_tmp(m:m+5) = str(i-1:i+4) - i = i + 4 - m = m + 5 + + ! validate the hex string: + if (valid_json_hex(str(i+1:i+4))) then + m = m + 1 + str_tmp(m:m+5) = str(i-1:i+4) + i = i + 4 + m = m + 5 + else + error_message = 'Error in unescape_string:'//& + ' Invalid hexadecimal sequence in string "'//& + trim(str)//'" ['//str(i-1:i+4)//']' + if (allocated(str_tmp)) deallocate(str_tmp) + return + end if else error_message = 'Error in unescape_string:'//& - ' Invalid hexadecimal sequence'//& - ' in string: '//str(i-1:) + ' Invalid hexadecimal sequence in string "'//& + trim(str)//'" ['//str(i-1:)//']' if (allocated(str_tmp)) deallocate(str_tmp) return end if - else + case default + !unknown escape character error_message = 'Error in unescape_string:'//& ' unknown escape sequence in string "'//& trim(str)//'" ['//backslash//c//']' if (allocated(str_tmp)) deallocate(str_tmp) return - end if + + end select else - !an escape character is the last character in - ! the string [this may not be valid syntax, - ! but just keep it] - m = m + 1 - str_tmp(m:m) = c + ! an escape character is the last character in + ! the string. This is an error. + error_message = 'Error in unescape_string:'//& + ' invalid escape character in string "'//& + trim(str)//'"' + if (allocated(str_tmp)) deallocate(str_tmp) + return end if else diff --git a/src/json_value_module.F90 b/src/json_value_module.F90 index 92480d7a8d..53e5911fd1 100644 --- a/src/json_value_module.F90 +++ b/src/json_value_module.F90 @@ -8752,11 +8752,11 @@ subroutine json_parse_file(json, file, p, unit) ! but we'll allocate something here just in case. p%name = trim(file) !use the file name - ! parse as a value + ! parse as a value call json%parse_value(unit=iunit, str=CK_'', value=p) - ! close the file if necessary - close(unit=iunit, iostat=istat) + ! close the file if necessary + close(unit=iunit, iostat=istat) ! check for errors: if (json%exception_thrown) then @@ -9868,22 +9868,22 @@ end subroutine parse_array ! * Jacob Williams : 6/16/2014 : Added hex validation. ! * Jacob Williams : 12/3/2015 : Fixed some bugs. ! * Jacob Williams : 8/23/2015 : `string` is now returned unescaped. +! * Jacob Williams : 7/21/2018 : moved hex validate to [[unescape_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 !! the string (unescaped if necessary) + 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 !! the string (unescaped + !! if necessary) logical(LK) :: eof !! end of file flag - logical(LK) :: is_hex !! it is a hex string - logical(LK) :: escape !! for escape string parsing character(kind=CK,len=1) :: c !! character returned by [[pop_char]] - character(kind=CK,len=4) :: hex !! hex string - integer(IK) :: i !! counter integer(IK) :: ip !! index to put next character, !! to speed up by reducing the number !! of character string reallocations. @@ -9895,10 +9895,7 @@ subroutine parse_string(json, unit, str, string) if (.not. json%exception_thrown) then !initialize: - ip = 1 - is_hex = .false. - escape = .false. - i = 0 + ip = 1 do @@ -9910,10 +9907,8 @@ subroutine parse_string(json, unit, str, string) 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 + else if (c==quotation_mark) then !end of string - if (is_hex) call json%throw_exception('Error in parse_string:'//& - ' incomplete hex string: \u'//trim(hex)) exit else @@ -9925,36 +9920,6 @@ subroutine parse_string(json, unit, str, 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==CK_'u') !the next four characters are the hex string - else - escape = (c==backslash) - end if - - end if - end if end do @@ -9968,7 +9933,8 @@ subroutine parse_string(json, unit, str, string) end if end if - !string is returned unescaped: + ! string is returned unescaped: + ! (this will also validate any hex strings present) call unescape_string(string,error_message) if (allocated(error_message)) then call json%throw_exception(error_message) From 8b74ef20df89c00e014620079b2caa6329a7db12 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Sat, 21 Jul 2018 14:55:22 -0500 Subject: [PATCH 03/10] 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. --- files/inputs/invalid3.json | 4 ++++ files/inputs/test1.json | 3 ++- src/json_file_module.F90 | 13 ++++++++--- src/json_value_module.F90 | 47 +++++++++++++++++++++++++++++--------- src/tests/jf_test_06.F90 | 29 +++++++++++++++++++---- src/tests/jf_test_10.F90 | 4 ++-- 6 files changed, 79 insertions(+), 21 deletions(-) create mode 100644 files/inputs/invalid3.json diff --git a/files/inputs/invalid3.json b/files/inputs/invalid3.json new file mode 100644 index 0000000000..e7b82d6c74 --- /dev/null +++ b/files/inputs/invalid3.json @@ -0,0 +1,4 @@ +{ +"a": "blah\", +"b": 2 +} diff --git a/files/inputs/test1.json b/files/inputs/test1.json index 4915f36aa4..abb957aecc 100644 --- a/files/inputs/test1.json +++ b/files/inputs/test1.json @@ -12,7 +12,8 @@ "..\\path\\to\\files\\file3.txt", "test \u2FA4 \uABCD \uABCD\uABCDtest", " test \\u \" blah\\\" test test", - "..\\path\\to\\files\\" + "..\\path\\to\\files\\", + "\\" ], "a": { "b": 1 diff --git a/src/json_file_module.F90 b/src/json_file_module.F90 index 6f5ffd9fc6..5c45b13d48 100644 --- a/src/json_file_module.F90 +++ b/src/json_file_module.F90 @@ -320,10 +320,17 @@ subroutine json_file_check_for_errors(me,status_ok,error_msg) implicit none class(json_file),intent(inout) :: me - logical(LK),intent(out) :: status_ok !! true if there were no errors - character(kind=CK,len=:),allocatable,intent(out) :: error_msg !! the error message (if there were errors) - + logical(LK),intent(out),optional :: status_ok !! true if there were no errors + character(kind=CK,len=:),allocatable,intent(out),optional :: error_msg !! the error message + !! (if there were errors) + +#if defined __GFORTRAN__ + character(kind=CK,len=:),allocatable :: tmp !! workaround for gfortran bugs + call me%core%check_for_errors(status_ok,tmp) + error_msg = tmp +#else call me%core%check_for_errors(status_ok,error_msg) +#endif end subroutine json_file_check_for_errors !***************************************************************************************** diff --git a/src/json_value_module.F90 b/src/json_value_module.F90 index 53e5911fd1..bad41b7724 100644 --- a/src/json_value_module.F90 +++ b/src/json_value_module.F90 @@ -1917,7 +1917,7 @@ end subroutine wrap_json_throw_exception ! * [[json_failed]] ! * [[json_throw_exception]] - pure subroutine json_check_for_errors(json,status_ok,error_msg) + subroutine json_check_for_errors(json,status_ok,error_msg) implicit none @@ -1927,6 +1927,10 @@ pure subroutine json_check_for_errors(json,status_ok,error_msg) !! (not allocated if !! there were no errors) +#if defined __GFORTRAN__ + character(kind=CK,len=:),allocatable :: tmp !! workaround for gfortran bugs +#endif + if (present(status_ok)) status_ok = .not. json%exception_thrown if (present(error_msg)) then @@ -1934,7 +1938,12 @@ pure subroutine json_check_for_errors(json,status_ok,error_msg) ! if an exception has been thrown, ! then this will always be allocated ! [see json_throw_exception] +#if defined __GFORTRAN__ + tmp = json%err_message + error_msg = tmp +#else error_msg = json%err_message +#endif end if end if @@ -8752,12 +8761,9 @@ subroutine json_parse_file(json, file, p, unit) ! but we'll allocate something here just in case. p%name = trim(file) !use the file name - ! parse as a value + ! parse as a value call json%parse_value(unit=iunit, str=CK_'', value=p) - ! close the file if necessary - close(unit=iunit, iostat=istat) - ! check for errors: if (json%exception_thrown) then call json%annotate_invalid_json(iunit,CK_'') @@ -8773,6 +8779,9 @@ subroutine json_parse_file(json, file, p, unit) end if end if + ! close the file: + close(unit=iunit, iostat=istat) + else 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) integer(IK) :: i_nl_prev !! index of previous newline character integer(IK) :: i_nl !! index of current newline character - ! If there was an error reading the file, then - ! print the line where the error occurred: + ! If there was an error reading the file, then + ! print the line where the error occurred: if (json%exception_thrown) then !the counters for the current line and the last character read: @@ -8918,8 +8927,13 @@ subroutine annotate_invalid_json(json,iunit,str) end if !create the error message: - if (allocated(json%err_message)) json%err_message = json%err_message//newline - json%err_message = 'line: '//trim(adjustl(line_str))//', '//& + if (allocated(json%err_message)) then + json%err_message = json%err_message//newline + else + json%err_message = '' + end if + json%err_message = json%err_message//& + 'line: '//trim(adjustl(line_str))//', '//& 'character: '//trim(adjustl(char_str))//newline//& trim(line)//newline//arrow_str @@ -9883,6 +9897,7 @@ subroutine parse_string(json, unit, str, string) !! if necessary) logical(LK) :: eof !! end of file flag + logical(LK) :: escape !! for escape string parsing character(kind=CK,len=1) :: c !! character returned by [[pop_char]] integer(IK) :: ip !! index to put next character, !! to speed up by reducing the number @@ -9895,7 +9910,8 @@ subroutine parse_string(json, unit, str, string) if (.not. json%exception_thrown) then !initialize: - ip = 1 + escape = .false. + ip = 1 do @@ -9907,7 +9923,7 @@ subroutine parse_string(json, unit, str, string) call json%throw_exception('Error in parse_string: Expecting end of string') return - else if (c==quotation_mark) then !end of string + else if (c==quotation_mark .and. .not. escape) then !end of string exit @@ -9920,6 +9936,15 @@ subroutine parse_string(json, unit, str, string) string(ip:ip) = c ip = ip + 1 + ! check for escape character, so we don't + ! exit prematurely if escaping a quotation + ! character: + if (escape) then + escape = .false. + else + escape = (c==backslash) + end if + end if end do diff --git a/src/tests/jf_test_06.F90 b/src/tests/jf_test_06.F90 index def5f64042..fb04a26ec7 100644 --- a/src/tests/jf_test_06.F90 +++ b/src/tests/jf_test_06.F90 @@ -7,7 +7,8 @@ module jf_test_6_mod - use json_module + use json_module, CK => json_CK, LK => json_LK + use json_parameters, only: newline use, intrinsic :: iso_fortran_env , only: error_unit, output_unit, wp => real64 implicit none @@ -29,9 +30,12 @@ subroutine test_6(error_cnt) type(json_file) :: json integer :: i + character(kind=CK,len=:),allocatable :: error_msg + logical(LK) :: status_ok - character(len=*),dimension(2),parameter :: files = ['invalid.json ',& - 'invalid2.json'] + character(len=*),dimension(3),parameter :: files = ['invalid.json ',& + 'invalid2.json',& + 'invalid3.json'] error_cnt = 0 call json%initialize() @@ -46,7 +50,7 @@ subroutine test_6(error_cnt) write(error_unit,'(A)') '=================================' write(error_unit,'(A)') '' - do i=1,2 + do i=1,size(files) ! parse the json file: write(error_unit,'(A)') '' @@ -54,7 +58,24 @@ subroutine test_6(error_cnt) write(error_unit,'(A)') '' call json%load_file(filename = dir//trim(files(i))) if (json%failed()) then + + if (i==1) then + call json%check_for_errors(status_ok, error_msg=error_msg) + + if (error_msg /= & + CK_'Error in parse_array: Unexpected character encountered when parsing array.'//newline//& + CK_'line: 13, character: 1'//newline//& + CK_'}'//newline//& + ''//newline//& + '^') then + ! verify that the expected error string is present + write(error_unit,'(A)') 'Error: unexpected error message string: "'//error_msg//'"' + error_cnt = error_cnt + 1 + end if + end if + call json%print_error_message(error_unit) + else write(error_unit,'(A)') 'An error should have been raised!' error_cnt = error_cnt + 1 diff --git a/src/tests/jf_test_10.F90 b/src/tests/jf_test_10.F90 index fefc1b429c..9723bb0c91 100644 --- a/src/tests/jf_test_10.F90 +++ b/src/tests/jf_test_10.F90 @@ -144,7 +144,7 @@ subroutine test_10(error_cnt) error_cnt = error_cnt + 1 else !also make sure the values are correct: - if (found .and. size(str_vec)==6 .and. & + if (found .and. size(str_vec)==7 .and. & str_vec(1)=='..\path\to\files\file1.txt') then write(error_unit,'(A)') '...success' else @@ -303,7 +303,7 @@ subroutine test_10(error_cnt) error_cnt = error_cnt + 1 else !also make sure the values are correct: - if (found .and. size(str_vec)==6 .and. & + if (found .and. size(str_vec)==7 .and. & str_vec(1)=='..\path\to\files\file1.txt') then write(error_unit,'(A)') '...success' else From b6571d84bcaebc0bc428c49e931fc4f61af0d001 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Sat, 21 Jul 2018 15:21:26 -0500 Subject: [PATCH 04/10] attempting to fix platform new line differences causing a unit test to fail. --- src/json_value_module.F90 | 11 ++++++++++- src/tests/jf_test_06.F90 | 2 -- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/json_value_module.F90 b/src/json_value_module.F90 index bad41b7724..e1c3aa39a7 100644 --- a/src/json_value_module.F90 +++ b/src/json_value_module.F90 @@ -8926,6 +8926,15 @@ subroutine annotate_invalid_json(json,iunit,str) line = CK_'' end if + ! add a newline for the error display if necessary: + line = trim(line) + if (len(line)>0) then + i = len(line) + if (line(i:i)/=newline) line = line//newline + else + line = line//newline + end if + !create the error message: if (allocated(json%err_message)) then json%err_message = json%err_message//newline @@ -8935,7 +8944,7 @@ subroutine annotate_invalid_json(json,iunit,str) json%err_message = json%err_message//& 'line: '//trim(adjustl(line_str))//', '//& 'character: '//trim(adjustl(char_str))//newline//& - trim(line)//newline//arrow_str + line//arrow_str if (allocated(line)) deallocate(line) diff --git a/src/tests/jf_test_06.F90 b/src/tests/jf_test_06.F90 index fb04a26ec7..6e9feb9cdf 100644 --- a/src/tests/jf_test_06.F90 +++ b/src/tests/jf_test_06.F90 @@ -61,12 +61,10 @@ subroutine test_6(error_cnt) if (i==1) then call json%check_for_errors(status_ok, error_msg=error_msg) - if (error_msg /= & CK_'Error in parse_array: Unexpected character encountered when parsing array.'//newline//& CK_'line: 13, character: 1'//newline//& CK_'}'//newline//& - ''//newline//& '^') then ! verify that the expected error string is present write(error_unit,'(A)') 'Error: unexpected error message string: "'//error_msg//'"' From 37e02acdcd729adc81fdf6d3394ba8322f7c06b4 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Sun, 22 Jul 2018 20:19:50 -0500 Subject: [PATCH 05/10] changed invalid.json file to linux line breaks so we can consistently have unit test 6 pass on all platforms. updated gitignore file for intel on windows. --- .gitignore | 3 ++- files/inputs/invalid.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index aecfd8f76e..20a4920b4f 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,8 @@ visual_studio/jsonfortranlib/ visual_studio/jsonfortrantest/Debug/ visual_studio/jsonfortrantest/Release/ visual_studio/jsonfortrantest/x64 - +visual_studio/config +My Advisor Results* My Amplifier* My Inspector* x64/ diff --git a/files/inputs/invalid.json b/files/inputs/invalid.json index 097356fa15..60def78a88 100644 --- a/files/inputs/invalid.json +++ b/files/inputs/invalid.json @@ -10,4 +10,4 @@ "..\\path\\to\\files\\file1.txt", "..\\path\\to\\files\\file2.txt", "..\\path\\to\\files\\file3.txt" -} +} \ No newline at end of file From d9c0a5bbb1f6d32950f3607cfcb71baba5456c29 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Sun, 22 Jul 2018 20:41:55 -0500 Subject: [PATCH 06/10] I don't understand why this is now failing on linux. added some debugging prints to see what is going on. --- src/tests/jf_test_06.F90 | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/tests/jf_test_06.F90 b/src/tests/jf_test_06.F90 index 6e9feb9cdf..2b7be638a5 100644 --- a/src/tests/jf_test_06.F90 +++ b/src/tests/jf_test_06.F90 @@ -29,8 +29,9 @@ subroutine test_6(error_cnt) integer,intent(out) :: error_cnt type(json_file) :: json - integer :: i + integer :: i, j character(kind=CK,len=:),allocatable :: error_msg + character(kind=CK,len=:),allocatable :: expected_error_msg logical(LK) :: status_ok character(len=*),dimension(3),parameter :: files = ['invalid.json ',& @@ -61,13 +62,20 @@ subroutine test_6(error_cnt) if (i==1) then call json%check_for_errors(status_ok, error_msg=error_msg) - if (error_msg /= & - CK_'Error in parse_array: Unexpected character encountered when parsing array.'//newline//& - CK_'line: 13, character: 1'//newline//& - CK_'}'//newline//& - '^') then + expected_error_msg = CK_'Error in parse_array: Unexpected charact9er encountered when parsing array.'//newline//& + CK_'line: 13, character: 1'//newline//& + CK_'}'//newline//'^' + if (error_msg /= expected_error_msg) then ! verify that the expected error string is present write(error_unit,'(A)') 'Error: unexpected error message string: "'//error_msg//'"' + write(error_unit,'(A)') '' + write(error_unit,*) 'len(error_msg) = ', len(error_msg) + write(error_unit,*) 'len(expected_error_msg) = ', len(expected_error_msg) + do j = 1, min(len(error_msg), len(expected_error_msg)) + if (error_msg(j:j) /= expected_error_msg(j:j)) then + write(error_unit,'(I3,1X,A,A,A,A,A)') j, '"', error_msg(j:j), '" /= "', expected_error_msg(j:j), '"' + end if + end do error_cnt = error_cnt + 1 end if end if From f9ce12f0a554d930d0c80616819150968280bf72 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Sun, 22 Jul 2018 20:47:00 -0500 Subject: [PATCH 07/10] oops --- src/tests/jf_test_06.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/jf_test_06.F90 b/src/tests/jf_test_06.F90 index 2b7be638a5..e8b5747f3a 100644 --- a/src/tests/jf_test_06.F90 +++ b/src/tests/jf_test_06.F90 @@ -62,7 +62,7 @@ subroutine test_6(error_cnt) if (i==1) then call json%check_for_errors(status_ok, error_msg=error_msg) - expected_error_msg = CK_'Error in parse_array: Unexpected charact9er encountered when parsing array.'//newline//& + expected_error_msg = CK_'Error in parse_array: Unexpected character encountered when parsing array.'//newline//& CK_'line: 13, character: 1'//newline//& CK_'}'//newline//'^' if (error_msg /= expected_error_msg) then From 7e5e8584e190d9fbdee58a5d1ac28f13f7889d8a Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Sun, 22 Jul 2018 20:57:56 -0500 Subject: [PATCH 08/10] more debugging on Travis --- src/tests/jf_test_06.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tests/jf_test_06.F90 b/src/tests/jf_test_06.F90 index e8b5747f3a..23fbab97cb 100644 --- a/src/tests/jf_test_06.F90 +++ b/src/tests/jf_test_06.F90 @@ -74,6 +74,8 @@ subroutine test_6(error_cnt) do j = 1, min(len(error_msg), len(expected_error_msg)) if (error_msg(j:j) /= expected_error_msg(j:j)) then write(error_unit,'(I3,1X,A,A,A,A,A)') j, '"', error_msg(j:j), '" /= "', expected_error_msg(j:j), '"' + else + write(error_unit,'(I3,1X,A,A,A,A,A)') j, '"', error_msg(j:j), '" == "', expected_error_msg(j:j), '"' end if end do error_cnt = error_cnt + 1 From d405bb21fe693e86fa41fd6c768026b51b94d375 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Sun, 22 Jul 2018 21:28:09 -0500 Subject: [PATCH 09/10] try this --- src/json_value_module.F90 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/json_value_module.F90 b/src/json_value_module.F90 index e1c3aa39a7..5794dac851 100644 --- a/src/json_value_module.F90 +++ b/src/json_value_module.F90 @@ -9028,9 +9028,14 @@ subroutine get_current_line_from_file_stream(json,iunit,line) end if istart = istart-1 !rewind until the beginning of the line end do - iend = json%ipos + iend = istart do read(iunit,pos=iend,iostat=ios) c + if (IS_IOSTAT_END(ios)) then + ! account for end of file without linebreak + iend=iend-1 + exit + end if if (c==newline .or. ios/=0) exit iend=iend+1 end do From 15da7e9862ae2e8e9b64d81273e2bf661292b132 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Sun, 22 Jul 2018 21:53:14 -0500 Subject: [PATCH 10/10] fix bug in recent commit. --- src/json_value_module.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/json_value_module.F90 b/src/json_value_module.F90 index 5794dac851..900fc626af 100644 --- a/src/json_value_module.F90 +++ b/src/json_value_module.F90 @@ -9028,7 +9028,7 @@ subroutine get_current_line_from_file_stream(json,iunit,line) end if istart = istart-1 !rewind until the beginning of the line end do - iend = istart + iend = json%ipos do read(iunit,pos=iend,iostat=ios) c if (IS_IOSTAT_END(ios)) then