Skip to content

Commit f86df6b

Browse files
committed
updated insert routine to account for list of elements being inserted.
1 parent 5925f1c commit f86df6b

File tree

2 files changed

+124
-16
lines changed

2 files changed

+124
-16
lines changed

src/json_value_module.F90

+70-15
Original file line numberDiff line numberDiff line change
@@ -2510,8 +2510,27 @@ end subroutine json_value_add_member
25102510
! end program test
25112511
!````
25122512
!
2513-
!@note This routine can be used to insert a new element
2514-
! into an array or object at a specific index.
2513+
!### Details
2514+
!
2515+
! * This routine can be used to insert a new element (or set of elements)
2516+
! into an array or object at a specific index.
2517+
! See [[json_value_insert_after_child_by_index]]
2518+
! * Children and subsequent elements of `element` are carried along.
2519+
! * If the inserted elements are part of an existing list, then
2520+
! they are removed from that list.
2521+
!
2522+
!````
2523+
! p
2524+
! [1] - [2] - [3] - [4]
2525+
! |
2526+
! [5] - [6] - [7] n=3 elements inserted
2527+
! element last
2528+
!
2529+
! Result is:
2530+
!
2531+
! [1] - [2] - [5] - [6] - [7] - [3] - [4]
2532+
!
2533+
!````
25152534

25162535
subroutine json_value_insert_after(json,p,element)
25172536

@@ -2524,30 +2543,66 @@ subroutine json_value_insert_after(json,p,element)
25242543
type(json_value),pointer :: element !! the element to insert after `p`
25252544

25262545
type(json_value),pointer :: parent !! the parent of `p`
2546+
type(json_value),pointer :: next !! temp pointer for traversing structure
2547+
type(json_value),pointer :: last !! the last of the items being inserted
2548+
integer :: n !! number of items being inserted
25272549

25282550
if (.not. json%exception_thrown) then
25292551

25302552
parent => p%parent
25312553

2554+
! set first parent of inserted list:
2555+
element%parent => parent
2556+
2557+
! Count the number of inserted elements.
2558+
! and set their parents.
2559+
n = 1 ! initialize counter
2560+
next => element%next
2561+
last => element
2562+
do
2563+
if (.not. associated(next)) exit
2564+
n = n + 1
2565+
next%parent => parent
2566+
last => next
2567+
next => next%next
2568+
end do
2569+
25322570
if (associated(parent)) then
2533-
element%parent => parent
2534-
parent%n_children = parent%n_children + 1
2535-
! if p is last in list have to update parent tail:
2536-
if (associated(parent%tail,p)) parent%tail => element
2537-
else
2538-
element%parent => null()
2571+
! update parent's child counter:
2572+
parent%n_children = parent%n_children + n
2573+
! if p is last of parents children then
2574+
! also have to update parent tail pointer:
2575+
if (associated(parent%tail,p)) then
2576+
parent%tail => last
2577+
end if
2578+
end if
2579+
2580+
if (associated(element%previous)) then
2581+
! element is apparently part of an existing list,
2582+
! so have to update that as well.
2583+
if (associated(element%previous%parent)) then
2584+
element%previous%parent%n_children = &
2585+
element%previous%parent%n_children - n
2586+
element%previous%parent%tail => &
2587+
element%previous ! now the last one in the list
2588+
else
2589+
! this would be a memory leak if the previous entries
2590+
! are not otherwise being pointed too
2591+
! [throw an error in this case???]
2592+
end if
2593+
!remove element from the other list:
2594+
element%previous%next => null()
25392595
end if
2596+
element%previous => p
25402597

2541-
!if there are any in the list after p:
25422598
if (associated(p%next)) then
2543-
element%next => p%next
2544-
element%next%previous => element
2599+
! if there are any in the list after p:
2600+
last%next => p%next
2601+
last%next%previous => element
25452602
else
2546-
element%next => null()
2603+
last%next => null()
25472604
end if
2548-
25492605
p%next => element
2550-
element%previous => p
25512606

25522607
end if
25532608

@@ -2557,7 +2612,7 @@ end subroutine json_value_insert_after
25572612
!*****************************************************************************************
25582613
!>
25592614
! Inserts `element` after the `idx`-th child of `p`,
2560-
! and updates the JSON structure accordingly. It is just
2615+
! and updates the JSON structure accordingly. This is just
25612616
! a wrapper for [[json_value_insert_after]].
25622617

25632618
subroutine json_value_insert_after_child_by_index(json,p,idx,element)

src/tests/jf_test_20.f90

+54-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ subroutine test_20(error_cnt)
2121
integer,intent(out) :: error_cnt !! report number of errors to caller
2222

2323
type(json_core) :: json
24-
type(json_value),pointer :: p,new,element
24+
type(json_value),pointer :: p,new,element,elements,root
2525
logical(lk) :: found,is_valid
2626
integer(IK),dimension(:),allocatable :: iarray
2727
character(kind=CK,len=:),allocatable :: error_msg
@@ -111,6 +111,59 @@ subroutine test_20(error_cnt)
111111
end if
112112
end if
113113

114+
! extract a set of elements from one array
115+
! and insert them into another:
116+
nullify(new)
117+
call json%create_object(root,'')
118+
call json%create_array(new,'array')
119+
call json%add(root,new)
120+
call json%add(new,'',100)
121+
call json%add(new,'',101)
122+
call json%add(new,'',102)
123+
124+
call json%get(root,'array',iarray)
125+
if (json%failed()) then
126+
call json%print_error_message(error_unit)
127+
error_cnt = error_cnt + 1
128+
end if
129+
130+
call json%get_child(new,2,elements)
131+
if (json%failed()) then
132+
call json%print_error_message(error_unit)
133+
error_cnt = error_cnt + 1
134+
else
135+
call json%insert_after(element,7,elements) ! insert new element after x(7)
136+
call json%get(p,'x',iarray)
137+
if (.not. all(iarray==[1,2,22,3,33,4,44,101,102])) then
138+
write(error_unit,'(A,1x,*(I3,1X))') 'Error: unexpected output:',iarray
139+
error_cnt = error_cnt + 1
140+
else
141+
write(error_unit,'(A,1x,*(I3,1X))') 'Success:',iarray
142+
end if
143+
144+
!also check original list, which should now have only 100
145+
call json%validate(new,is_valid,error_msg)
146+
if (.not. is_valid) then
147+
write(error_unit,'(A)') trim(error_msg)
148+
error_cnt = error_cnt + 1
149+
else
150+
!check contents:
151+
call json%get(root,'array',iarray)
152+
if (json%failed()) then
153+
call json%print_error_message(error_unit)
154+
error_cnt = error_cnt + 1
155+
else
156+
if (.not. all(iarray==[100])) then
157+
write(error_unit,'(A,1x,*(I3,1X))') 'Error: unexpected output:',iarray
158+
error_cnt = error_cnt + 1
159+
else
160+
write(error_unit,'(A,1x,*(I3,1X))') 'Success:',iarray
161+
end if
162+
end if
163+
end if
164+
165+
end if
166+
114167
call json%validate(p,is_valid,error_msg)
115168
if (.not. is_valid) then
116169
write(error_unit,'(A)') trim(error_msg)

0 commit comments

Comments
 (0)