@@ -4797,156 +4797,162 @@ subroutine json_get_string(me, value)
4797
4797
type (json_value),pointer ,intent (in ) :: me
4798
4798
character (kind= CK,len= :),allocatable ,intent (out ) :: value
4799
4799
4800
- character (kind= CK ,len= :),allocatable :: s,pre,post
4801
- integer (IK) :: j,jprev,n
4802
- character (kind= CK,len= 1 ) :: c
4803
-
4804
4800
value = ' '
4805
- if ( exception_thrown) return
4801
+ if (.not. exception_thrown) then
4806
4802
4807
- select case (me% var_type)
4803
+ select case (me% var_type)
4808
4804
4809
- case (json_string)
4805
+ case (json_string)
4810
4806
4811
- if (allocated (me% str_value)) then
4807
+ if (allocated (me% str_value)) then
4808
+ call unescape_string(me% str_value, value)
4809
+ else
4810
+ call throw_exception(' Error in json_get_string:' // &
4811
+ ' me%str_value not allocated' )
4812
+ end if
4812
4813
4813
- ! get the value as is:
4814
- s = me% str_value
4814
+ case default
4815
4815
4816
- ! Now, have to remove the escape characters:
4817
- !
4818
- ! '\"' quotation mark
4819
- ! '\\' reverse solidus
4820
- ! '\/' solidus
4821
- ! '\b' backspace
4822
- ! '\f' formfeed
4823
- ! '\n' newline (LF)
4824
- ! '\r' carriage return (CR)
4825
- ! '\t' horizontal tab
4826
- ! '\uXXXX' 4 hexadecimal digits
4827
- !
4816
+ call throw_exception(' Error in json_get_string:' // &
4817
+ ' Unable to resolve value to characters: ' // me% name)
4828
4818
4829
- ! initialize:
4830
- n = len (s)
4831
- j = 1
4819
+ ! Note: for the other cases, we could do val to string conversions.
4832
4820
4833
- do
4821
+ end select
4834
4822
4835
- jprev = j ! initialize
4836
- j = index (s(j:n),backslash) ! look for an escape character
4823
+ end if
4837
4824
4838
- if (j> 0 ) then ! an escape character was found
4825
+ end subroutine json_get_string
4826
+ ! *****************************************************************************************
4839
4827
4840
- ! index in full string of the escape character:
4841
- j = j + (jprev-1 )
4828
+ ! *****************************************************************************************
4829
+ ! >
4830
+ ! Remove the escape characters from a JSON string and return it.
4831
+ !
4832
+ ! The escaped characters are denoted by the '\' character:
4833
+ ! ````
4834
+ ! '\"' quotation mark
4835
+ ! '\\' reverse solidus
4836
+ ! '\/' solidus
4837
+ ! '\b' backspace
4838
+ ! '\f' formfeed
4839
+ ! '\n' newline (LF)
4840
+ ! '\r' carriage return (CR)
4841
+ ! '\t' horizontal tab
4842
+ ! '\uXXXX' 4 hexadecimal digits
4843
+ ! ````
4842
4844
4843
- if (j < n) then
4845
+ subroutine unescape_string ( str_in , str_out )
4844
4846
4845
- ! save the bit before the escape character:
4846
- if (j> 1 ) then
4847
- pre = s( 1 : j-1 )
4848
- else
4849
- pre = ' '
4850
- end if
4847
+ implicit none
4848
+
4849
+ character (kind= CK,len=* ),intent (in ) :: str_in ! ! string as stored in a [[json_value]]
4850
+ character (kind= CK,len= :),allocatable ,intent (out ) :: str_out ! ! decoded string
4851
+
4852
+ integer :: i ! ! counter
4853
+ integer :: n ! ! length of str_in
4854
+ integer :: m ! ! length of str_out
4855
+ character (kind= CK,len= 1 ) :: c ! ! for scanning each character in string
4851
4856
4852
- ! character after the escape character:
4853
- c = s( j+1 : j+1 )
4854
-
4855
- if (any (c == [quotation_mark,backslash,slash, &
4856
- to_unicode([' b' ,' f' ,' n' ,' r' ,' t' ])])) then
4857
-
4858
- ! save the bit after the escape characters:
4859
- if (j+2 < n) then
4860
- post = s(j+2 :n)
4861
- else
4862
- post = ' '
4863
- end if
4864
-
4865
- select case (c)
4866
- case (quotation_mark,backslash,slash)
4867
- ! use c as is
4868
- case (CK_' b' )
4869
- c = bspace
4870
- case (CK_' f' )
4871
- c = formfeed
4872
- case (CK_' n' )
4873
- c = newline
4874
- case (CK_' r' )
4875
- c = carriage_return
4876
- case (CK_' t' )
4877
- c = horizontal_tab
4878
- end select
4879
-
4880
- s = pre// c// post
4881
-
4882
- n = n-1 ! backslash character has been
4883
- ! removed from the string
4884
-
4885
- else if (c == ' u' ) then ! expecting 4 hexadecimal digits after
4886
- ! the escape character [\uXXXX]
4887
-
4888
- ! for now, we are just printing them as is
4889
- ! [not checking to see if it is a valid hex value]
4890
-
4891
- if (j+5 <= n) then
4892
- j= j+4
4893
- else
4894
- call throw_exception(' Error in json_get_string:' // &
4895
- ' Invalid hexadecimal sequence' // &
4896
- ' in string: ' // trim (c))
4897
- exit
4898
- end if
4857
+ if (scan (str_in,backslash)>0 ) then
4899
4858
4859
+ ! there is at least one escape character, so process this string:
4860
+
4861
+ n = len (str_in)
4862
+ str_out = repeat (space,n) ! size the output string (will be trimmed later)
4863
+ m = 0 ! counter in str_out
4864
+ i = 0 ! counter in str_in
4865
+
4866
+ do
4867
+
4868
+ i = i + 1
4869
+ if (i> n) exit ! finished
4870
+ c = str_in(i:i) ! get next character in the string
4871
+
4872
+ if (c == backslash) then
4873
+
4874
+ if (i< n) then
4875
+
4876
+ i = i + 1
4877
+ c = str_in(i:i) ! character after the escape
4878
+
4879
+ if (any (c == [quotation_mark,backslash,slash, &
4880
+ to_unicode([' b' ,' f' ,' n' ,' r' ,' t' ])])) then
4881
+
4882
+ select case (c)
4883
+ case (quotation_mark,backslash,slash)
4884
+ ! use d as is
4885
+ case (CK_' b' )
4886
+ c = bspace
4887
+ case (CK_' f' )
4888
+ c = formfeed
4889
+ case (CK_' n' )
4890
+ c = newline
4891
+ case (CK_' r' )
4892
+ c = carriage_return
4893
+ case (CK_' t' )
4894
+ c = horizontal_tab
4895
+ end select
4896
+
4897
+ m = m + 1
4898
+ str_out(m:m) = c
4899
+
4900
+ else if (c == ' u' ) then ! expecting 4 hexadecimal digits after
4901
+ ! the escape character [\uXXXX]
4902
+
4903
+ ! for now, we are just returning them as is
4904
+ ! [not checking to see if it is a valid hex value]
4905
+ !
4906
+ ! Example:
4907
+ ! 123456
4908
+ ! \uXXXX
4909
+
4910
+ if (i+4 <= n) then
4911
+ m = m + 1
4912
+ str_out(m:m+5 ) = str_in(i-1 :i+4 )
4913
+ i = i + 4
4914
+ m = m + 5
4900
4915
else
4901
- ! unknown escape character
4902
4916
call throw_exception(' Error in json_get_string:' // &
4903
- ' unknown escape sequence in string "' // &
4904
- trim (s)// ' " [' // backslash// c// ' ]' )
4905
- exit
4917
+ ' Invalid hexadecimal sequence' // &
4918
+ ' in string: ' // str_in(i-1 :))
4919
+ str_out = ' '
4920
+ return
4906
4921
end if
4907
4922
4908
- j= j+1 ! go to the next character
4909
-
4910
- if (j>= n) exit ! finished
4911
-
4912
4923
else
4913
- ! an escape character is the last character in
4914
- ! the string [this may not be valid syntax,
4915
- ! but just keep it]
4916
- exit
4924
+ ! unknown escape character
4925
+ call throw_exception(' Error in json_get_string:' // &
4926
+ ' unknown escape sequence in string "' // &
4927
+ trim (str_in)// ' " [' // backslash// c// ' ]' )
4928
+ str_out = ' '
4929
+ return
4917
4930
end if
4918
4931
4919
4932
else
4920
- exit ! no more escape characters in the string
4933
+ ! an escape character is the last character in
4934
+ ! the string [this may not be valid syntax,
4935
+ ! but just keep it]
4936
+ m = m + 1
4937
+ str_out(m:m) = c
4921
4938
end if
4922
4939
4923
- end do
4924
-
4925
- if (exception_thrown) then
4926
- if (allocated (value)) deallocate (value)
4927
4940
else
4928
- value = s
4941
+ m = m + 1
4942
+ str_out(m:m) = c
4929
4943
end if
4930
4944
4931
- else
4932
- call throw_exception(' Error in json_get_string:' // &
4933
- ' me%value not allocated' )
4934
- end if
4935
-
4936
- case default
4937
- call throw_exception(' Error in json_get_string:' // &
4938
- ' Unable to resolve value to characters: ' // me% name)
4939
-
4940
- ! Note: for the other cases, we could do val to string conversions.
4945
+ end do
4941
4946
4942
- end select
4947
+ ! trim trailing space:
4948
+ str_out = str_out(1 :m)
4943
4949
4944
- ! cleanup:
4945
- if ( allocated (s)) deallocate (s)
4946
- if ( allocated (pre)) deallocate (pre)
4947
- if ( allocated (post)) deallocate (post)
4950
+ else
4951
+ ! there are no escape characters, so return as is:
4952
+ str_out = str_in
4953
+ end if
4948
4954
4949
- end subroutine json_get_string
4955
+ end subroutine unescape_string
4950
4956
! *****************************************************************************************
4951
4957
4952
4958
! *****************************************************************************************
@@ -6383,6 +6389,7 @@ end subroutine parse_array
6383
6389
!
6384
6390
! # History
6385
6391
! * Jacob Williams : 6/16/2014 : Added hex validation.
6392
+ ! * Jacob Williams : 12/3/2015 : Fixed some bugs.
6386
6393
6387
6394
subroutine parse_string (unit , str , string )
6388
6395
@@ -6393,7 +6400,7 @@ subroutine parse_string(unit, str, string)
6393
6400
character (kind= CK,len= :),allocatable ,intent (out ) :: string
6394
6401
6395
6402
logical (LK) :: eof, is_hex, escape
6396
- character (kind= CK,len= 1 ) :: c, last
6403
+ character (kind= CK,len= 1 ) :: c
6397
6404
character (kind= CK,len= 4 ) :: hex
6398
6405
integer (IK) :: i
6399
6406
integer (IK) :: ip ! ! index to put next character,
@@ -6406,7 +6413,6 @@ subroutine parse_string(unit, str, string)
6406
6413
6407
6414
! initialize:
6408
6415
ip = 1
6409
- last = space
6410
6416
is_hex = .false.
6411
6417
escape = .false.
6412
6418
i = 0
@@ -6421,7 +6427,7 @@ subroutine parse_string(unit, str, string)
6421
6427
call throw_exception(' Error in parse_string: Expecting end of string' )
6422
6428
return
6423
6429
6424
- else if (c== quotation_mark .and. last /= backslash ) then
6430
+ else if (c== quotation_mark .and. .not. escape ) then ! end of string
6425
6431
6426
6432
if (is_hex) call throw_exception(' Error in parse_string:' // &
6427
6433
' incomplete hex string: \u' // trim (hex))
@@ -6466,9 +6472,6 @@ subroutine parse_string(unit, str, string)
6466
6472
6467
6473
end if
6468
6474
6469
- ! update for next char:
6470
- last = c
6471
-
6472
6475
end if
6473
6476
6474
6477
end do
0 commit comments