@@ -520,6 +520,9 @@ module json_value_module
520
520
procedure ,public :: swap = > json_value_swap ! ! Swap two [[json_value]] pointers
521
521
! ! in a structure (or two different structures).
522
522
procedure ,public :: is_child_of = > json_value_is_child_of ! ! Check if a [[json_value]] is a child of another.
523
+ procedure ,public :: validate = > json_value_validate ! ! Check that a [[json_value]] linked list is valid
524
+ ! ! (i.e., is properly constructed). This may be
525
+ ! ! useful if it has been constructed externally.
523
526
524
527
! other private routines:
525
528
procedure :: name_equal
@@ -1581,6 +1584,206 @@ end subroutine is_child_of_callback
1581
1584
end function json_value_is_child_of
1582
1585
! *****************************************************************************************
1583
1586
1587
+ ! *****************************************************************************************
1588
+ ! > author: Jacob Williams
1589
+ ! date: 5/2/2016
1590
+ !
1591
+ ! Validate a [[json_value]] linked list by checking to make sure
1592
+ ! all the pointers are properly associated, arrays and objects
1593
+ ! have the correct number of children, and the correct data is
1594
+ ! allocated for the variable types.
1595
+ !
1596
+ ! It recursively traverses the entire structure and checks every element.
1597
+ !
1598
+ ! @note This routine does not check or throw any exceptions.
1599
+
1600
+ subroutine json_value_validate (json ,p ,is_valid ,error_msg )
1601
+
1602
+ implicit none
1603
+
1604
+ class(json_core),intent (inout ) :: json
1605
+ type (json_value),pointer ,intent (in ) :: p
1606
+ logical (LK),intent (out ) :: is_valid ! ! True if the structure is valid.
1607
+ character (kind= CK,len= :),allocatable :: error_msg ! ! if not valid, this will contain
1608
+ ! ! a description of the problem
1609
+
1610
+ if (associated (p)) then
1611
+ is_valid = .true.
1612
+ call check_if_valid(p,require_parent= associated (p% parent))
1613
+ else
1614
+ error_msg = ' The pointer is not associated'
1615
+ is_valid = .false.
1616
+ end if
1617
+
1618
+ contains
1619
+
1620
+ recursive subroutine check_if_valid (p ,require_parent )
1621
+
1622
+ implicit none
1623
+
1624
+ type (json_value),pointer ,intent (in ) :: p
1625
+ logical ,intent (in ) :: require_parent ! ! the first one may be a root (so no parent),
1626
+ ! ! but all descendants must have a parent.
1627
+
1628
+ integer :: i ! ! counter
1629
+ type (json_value),pointer :: element
1630
+ type (json_value),pointer :: previous
1631
+
1632
+ if (is_valid .and. associated (p)) then
1633
+
1634
+ ! data type:
1635
+ select case (p% var_type)
1636
+ case (json_null,json_object,json_array)
1637
+ if (allocated (p% log_value) .or. allocated (p% int_value) .or. &
1638
+ allocated (p% dbl_value) .or. allocated (p% str_value)) then
1639
+ error_msg = ' incorrect data allocated for ' // &
1640
+ ' json_null, json_object, or json_array variable type'
1641
+ is_valid = .false.
1642
+ return
1643
+ end if
1644
+ case (json_logical)
1645
+ if (.not. allocated (p% log_value)) then
1646
+ error_msg = ' log_value should be allocated for json_logical variable type'
1647
+ is_valid = .false.
1648
+ return
1649
+ else if (allocated (p% int_value) .or. &
1650
+ allocated (p% dbl_value) .or. allocated (p% str_value)) then
1651
+ error_msg = ' incorrect data allocated for json_logical variable type'
1652
+ is_valid = .false.
1653
+ return
1654
+ end if
1655
+ case (json_integer)
1656
+ if (.not. allocated (p% int_value)) then
1657
+ error_msg = ' int_value should be allocated for json_integer variable type'
1658
+ is_valid = .false.
1659
+ return
1660
+ else if (allocated (p% log_value) .or. &
1661
+ allocated (p% dbl_value) .or. allocated (p% str_value)) then
1662
+ error_msg = ' incorrect data allocated for json_integer variable type'
1663
+ is_valid = .false.
1664
+ return
1665
+ end if
1666
+ case (json_double)
1667
+ if (.not. allocated (p% dbl_value)) then
1668
+ error_msg = ' dbl_value should be allocated for json_double variable type'
1669
+ is_valid = .false.
1670
+ return
1671
+ else if (allocated (p% log_value) .or. allocated (p% int_value) .or. &
1672
+ allocated (p% str_value)) then
1673
+ error_msg = ' incorrect data allocated for json_double variable type'
1674
+ is_valid = .false.
1675
+ return
1676
+ end if
1677
+ case (json_string)
1678
+ if (.not. allocated (p% str_value)) then
1679
+ error_msg = ' str_value should be allocated for json_string variable type'
1680
+ is_valid = .false.
1681
+ return
1682
+ else if (allocated (p% log_value) .or. allocated (p% int_value) .or. &
1683
+ allocated (p% dbl_value)) then
1684
+ error_msg = ' incorrect data allocated for json_string variable type'
1685
+ is_valid = .false.
1686
+ return
1687
+ end if
1688
+ case default
1689
+ error_msg = ' invalid JSON variable type'
1690
+ is_valid = .false.
1691
+ return
1692
+ end select
1693
+
1694
+ if (require_parent .and. .not. associated (p% parent)) then
1695
+ error_msg = ' parent pointer is not associated'
1696
+ is_valid = .false.
1697
+ return
1698
+ end if
1699
+
1700
+ if (.not. allocated (p% name)) then
1701
+ if (associated (p% parent)) then
1702
+ if (p% parent% var_type/= json_array) then
1703
+ error_msg = ' JSON variable must have a name if not an ' // &
1704
+ ' array element or the root'
1705
+ is_valid = .false.
1706
+ return
1707
+ end if
1708
+ end if
1709
+ end if
1710
+
1711
+ if (associated (p% children) .neqv. associated (p% tail)) then
1712
+ error_msg = ' both children and tail pointers must be associated'
1713
+ is_valid = .false.
1714
+ return
1715
+ end if
1716
+
1717
+ ! now, check next one:
1718
+ if (associated (p% next)) then
1719
+ call check_if_valid(p% next,require_parent= require_parent)
1720
+ end if
1721
+
1722
+ if (associated (p% children)) then
1723
+
1724
+ if (p% var_type/= json_array .and. p% var_type/= json_object) then
1725
+ error_msg = ' only arrays and objects can have children'
1726
+ is_valid = .false.
1727
+ return
1728
+ end if
1729
+
1730
+ ! first validate children pointers:
1731
+
1732
+ previous = > null ()
1733
+ element = > p% children
1734
+ do i = 1 , p% n_children
1735
+ if (.not. associated (element% parent,p)) then
1736
+ error_msg = ' child'' s parent pointer not properly associated'
1737
+ is_valid = .false.
1738
+ return
1739
+ end if
1740
+ if (i== 1 .and. associated (element% previous)) then
1741
+ error_msg = ' first child shouldn'' t have a previous'
1742
+ is_valid = .false.
1743
+ return
1744
+ end if
1745
+ if (i< p% n_children .and. .not. associated (element% next)) then
1746
+ error_msg = ' not enough children'
1747
+ is_valid = .false.
1748
+ return
1749
+ end if
1750
+ if (i== p% n_children .and. associated (element% next)) then
1751
+ error_msg = ' too many children'
1752
+ is_valid = .false.
1753
+ return
1754
+ end if
1755
+ if (i> 1 ) then
1756
+ if (.not. associated (previous,element% previous)) then
1757
+ error_msg = ' previous pointer not properly associated'
1758
+ is_valid = .false.
1759
+ return
1760
+ end if
1761
+ end if
1762
+ if (i== p% n_children .and. &
1763
+ .not. associated (element% parent% tail,element)) then
1764
+ error_msg = ' parent'' s tail pointer not properly associated'
1765
+ is_valid = .false.
1766
+ return
1767
+ end if
1768
+ if (i< p% n_children) then
1769
+ ! setup next case:
1770
+ previous = > element
1771
+ element = > element% next
1772
+ end if
1773
+ end do
1774
+
1775
+ ! now check all the children:
1776
+ call check_if_valid(p% children,require_parent= .true. )
1777
+
1778
+ end if
1779
+
1780
+ end if
1781
+
1782
+ end subroutine check_if_valid
1783
+
1784
+ end subroutine json_value_validate
1785
+ ! *****************************************************************************************
1786
+
1584
1787
! *****************************************************************************************
1585
1788
! > author: Jacob Williams
1586
1789
! date: 12/6/2014
0 commit comments