Skip to content

Commit 2a771a2

Browse files
Merge pull request #335 from jacobwilliams/clone-fix
json_clone fix
2 parents b206494 + 38f4f85 commit 2a771a2

File tree

2 files changed

+126
-3
lines changed

2 files changed

+126
-3
lines changed

src/json_value_module.F90

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,13 @@ end function name_strings_equal
11031103
!
11041104
! Create a deep copy of a [[json_value]] linked-list structure.
11051105
!
1106+
!### Notes
1107+
!
1108+
! * If `from` has children, then they are also cloned.
1109+
! * The parent of `from` is not linked to `to`.
1110+
! * If `from` is an element of an array, then the previous and
1111+
! next entries are not cloned (only that element and it's children, if any).
1112+
!
11061113
!### Example
11071114
!
11081115
!````fortran
@@ -1182,10 +1189,12 @@ recursive subroutine json_value_clone_func(from,to,parent,previous,next,children
11821189
if (present(next)) to%next => next
11831190
if (present(children)) to%children => children
11841191
if (present(tail)) then
1185-
if (tail) to%parent%tail => to
1192+
if (tail .and. associated(to%parent)) to%parent%tail => to
11861193
end if
11871194

1188-
if (associated(from%next)) then
1195+
if (associated(from%next) .and. associated(to%parent)) then
1196+
! we only clone the next entry in an array
1197+
! if the parent has also been cloned
11891198
allocate(to%next)
11901199
call json_value_clone_func(from%next,&
11911200
to%next,&
@@ -2643,7 +2652,9 @@ recursive subroutine check_if_valid(p,require_parent)
26432652

26442653
! now, check next one:
26452654
if (associated(p%next)) then
2646-
call check_if_valid(p%next,require_parent=require_parent)
2655+
! if it's an element in an
2656+
! array, then require a parent:
2657+
call check_if_valid(p%next,require_parent=.true.)
26472658
end if
26482659

26492660
if (associated(p%children)) then

src/tests/jf_test_33.F90

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
!*****************************************************************************************
2+
!>
3+
! Module for the 33rd unit test.
4+
5+
module jf_test_33_mod
6+
7+
use json_module, rk => json_rk, lk => json_lk, ik => json_ik, ck => json_ck, cdk => json_cdk
8+
use, intrinsic :: iso_fortran_env , only: error_unit, output_unit
9+
10+
implicit none
11+
12+
private
13+
public :: test_33
14+
15+
contains
16+
17+
subroutine test_33(error_cnt)
18+
19+
!! Test the clone routine
20+
21+
implicit none
22+
23+
integer,intent(out) :: error_cnt
24+
25+
type(json_core) :: json
26+
type(json_value),pointer :: p, p_var, p_var_clone
27+
integer :: i !! counter
28+
logical(LK) :: is_valid !! True if the structure is valid.
29+
character(kind=CK,len=:),allocatable :: error_msg !! if not valid, this will contain
30+
!! a description of the problem
31+
32+
character(kind=CK,len=*),parameter :: json_string = CK_'{ "struct": {"a": [{"b":1},{"b":2}]} }'
33+
34+
character(kind=CK,len=*),dimension(5),parameter :: keys = [ CK_'$ ',&
35+
CK_'struct ',&
36+
CK_'struct.a ',&
37+
CK_'struct.a(1) ',&
38+
CK_'struct.a(1).b' ]
39+
40+
error_cnt = 0
41+
42+
write(error_unit,'(A)') ''
43+
write(error_unit,'(A)') '================================='
44+
write(error_unit,'(A)') ' TEST 33'
45+
write(error_unit,'(A)') '================================='
46+
write(error_unit,'(A)') ''
47+
48+
call json%initialize()
49+
50+
call json%parse(p,json_string)
51+
if (json%failed()) then
52+
call json%print_error_message(error_unit)
53+
error_cnt = error_cnt + 1
54+
else
55+
56+
do i = 1, size(keys)
57+
write(error_unit,'(A)') 'Cloning "'//trim(keys(i))//'" ...'
58+
call json%get(p,trim(keys(i)),p_var)
59+
if (json%failed()) then
60+
call json%print_error_message(error_unit)
61+
error_cnt = error_cnt + 1
62+
exit
63+
end if
64+
call json%clone(p_var, p_var_clone)
65+
if (json%failed()) then
66+
call json%print_error_message(error_unit)
67+
error_cnt = error_cnt + 1
68+
exit
69+
end if
70+
call json%print(p_var_clone,output_unit)
71+
call json%validate(p_var_clone,is_valid,error_msg)
72+
if (.not. is_valid) then
73+
error_cnt = error_cnt + 1
74+
write(error_unit,*) error_msg
75+
else
76+
write(error_unit,*) '... Valid'
77+
end if
78+
call json%destroy(p_var_clone) ! free memory
79+
write(error_unit,*) ''
80+
end do
81+
82+
end if
83+
84+
if (.not. json%failed() .and. error_cnt==0) then
85+
write(error_unit,'(A)') 'Success!'
86+
else
87+
write(error_unit,'(A)') 'Test Failed!'
88+
end if
89+
90+
call json%destroy(p) ! free memory
91+
92+
end subroutine test_33
93+
94+
end module jf_test_33_mod
95+
!*****************************************************************************************
96+
97+
#ifndef INTERGATED_TESTS
98+
!*****************************************************************************************
99+
program jf_test_33
100+
101+
!! 33rd unit test.
102+
103+
use jf_test_33_mod , only: test_33
104+
implicit none
105+
integer :: n_errors
106+
n_errors = 0
107+
call test_33(n_errors)
108+
if (n_errors /= 0) stop 1
109+
110+
end program jf_test_33
111+
!*****************************************************************************************
112+
#endif

0 commit comments

Comments
 (0)