!***************************************************************************************** !> author: Jacob Williams ! license: BSD ! ! Higher-level [[json_file]] interface for the [[json_value]] type. ! !### License ! * JSON-Fortran is released under a BSD-style license. ! See the [LICENSE](https://github.com/jacobwilliams/json-fortran/blob/master/LICENSE) ! file for details. module json_file_module use,intrinsic :: iso_fortran_env use json_kinds use json_parameters, only: unit2str use json_string_utilities use json_value_module use json_hash_module implicit none private #include "json_macros.inc" !********************************************************* !> author: Jacob Williams ! date: 12/9/2013 ! ! The `json_file` is the main public class that is ! used to open a file and get data from it. ! ! A `json_file` contains only two items: an instance of a [[json_core(type)]], ! which is used for all data manipulation, and a [[json_value]] pointer, ! which is used to construct the linked-list data structure. ! Note that most methods in the `json_file` class are simply wrappers ! to the lower-level routines in the [[json_value_module]]. ! !### Example ! !```fortran ! program test ! use json_module ! implicit none ! type(json_file) :: json ! integer :: ival ! real(real64) :: rval ! character(len=:),allocatable :: cval ! logical :: found ! call json%initialize(compact_reals=.true.) ! call json%load(filename='myfile.json') ! call json%print() !print to the console ! call json%get('var.i',ival,found) ! call json%get('var.r(3)',rval,found) ! call json%get('var.c',cval,found) ! call json%destroy() ! end program test !``` ! !@note The `destroy()` method may be called to free the memory if necessary. ! [[json_file(type)]] includes a finalizer that also calls ! `destroy()` when the variable goes out of scope. type,public :: json_file private 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 ! this class also has the option to use a hash table logical :: hash_enabled = .false. !! whether to use a hash table for this file type(json_hash_table) :: hash !! the hash table for this file (if enabled) contains generic,public :: initialize => initialize_json_core_in_file,& set_json_core_in_file procedure,public :: get_core => get_json_core_in_file !> ! Load JSON from a file. procedure,public :: load => json_file_load !> ! The same as `load`, but only here for backward compatibility procedure,public :: load_file => json_file_load !> ! Load JSON from a string. generic,public :: deserialize => MAYBEWRAP(json_file_load_from_string) !> ! The same as `deserialize`, but only here for backward compatibility generic,public :: load_from_string => MAYBEWRAP(json_file_load_from_string) !> ! Print the [[json_value]] structure to an allocatable string procedure,public :: serialize => json_file_print_to_string !> ! The same as `serialize`, but only here for backward compatibility procedure,public :: print_to_string => json_file_print_to_string procedure,public :: destroy => json_file_destroy procedure,public :: nullify => json_file_nullify procedure,public :: move => json_file_move_pointer generic,public :: info => MAYBEWRAP(json_file_variable_info) generic,public :: matrix_info => MAYBEWRAP(json_file_variable_matrix_info) !error checking: procedure,public :: failed => json_file_failed procedure,public :: print_error_message => json_file_print_error_message procedure,public :: check_for_errors => json_file_check_for_errors procedure,public :: clear_exceptions => json_file_clear_exceptions procedure :: throw_exception generic,public :: print => json_file_print_to_console, & json_file_print_to_unit, & json_file_print_to_filename !> ! The same as `print`, but only here for backward compatibility generic,public :: print_file => json_file_print_to_console, & json_file_print_to_unit, & json_file_print_to_filename !> ! Rename a variable, specifying it by path generic,public :: rename => MAYBEWRAP(json_file_rename) #ifdef USE_UCS4 generic,public :: rename => json_file_rename_path_ascii, & json_file_rename_name_ascii #endif !> ! Verify that a path is valid ! (i.e., a variable with this path exists in the file). generic,public :: valid_path => MAYBEWRAP(json_file_valid_path) !> ! Get a variable from a [[json_file(type)]], by specifying the path. generic,public :: get => MAYBEWRAP(json_file_get_object), & MAYBEWRAP(json_file_get_integer), & #ifndef REAL32 MAYBEWRAP(json_file_get_real32), & #endif MAYBEWRAP(json_file_get_real), & #ifdef REAL128 MAYBEWRAP(json_file_get_real64), & #endif MAYBEWRAP(json_file_get_logical), & MAYBEWRAP(json_file_get_string), & MAYBEWRAP(json_file_get_integer_vec), & #ifndef REAL32 MAYBEWRAP(json_file_get_real32_vec), & #endif MAYBEWRAP(json_file_get_real_vec), & #ifdef REAL128 MAYBEWRAP(json_file_get_real64_vec), & #endif MAYBEWRAP(json_file_get_logical_vec), & MAYBEWRAP(json_file_get_string_vec), & MAYBEWRAP(json_file_get_alloc_string_vec), & json_file_get_root !> ! Add a variable to a [[json_file(type)]], by specifying the path. ! !### Example ! !```fortran ! program test ! use json_module, rk=>json_rk, ik=>json_ik ! implicit none ! type(json_file) :: f ! call f%initialize() ! specify whatever init options you want. ! call f%add('inputs.t', 0.0_rk) ! call f%add('inputs.x', [1.0_rk,2.0_rk,3.0_rk]) ! call f%add('inputs.flag', .true.) ! call f%print() ! print to the console ! end program test !``` generic,public :: add => json_file_add, & MAYBEWRAP(json_file_add_object), & MAYBEWRAP(json_file_add_integer), & #ifndef REAL32 MAYBEWRAP(json_file_add_real32), & #endif MAYBEWRAP(json_file_add_real), & #ifdef REAL128 MAYBEWRAP(json_file_add_real64), & #endif MAYBEWRAP(json_file_add_logical), & MAYBEWRAP(json_file_add_string), & MAYBEWRAP(json_file_add_integer_vec), & #ifndef REAL32 MAYBEWRAP(json_file_add_real32_vec), & #endif MAYBEWRAP(json_file_add_real_vec), & #ifdef REAL128 MAYBEWRAP(json_file_add_real64_vec), & #endif MAYBEWRAP(json_file_add_logical_vec), & MAYBEWRAP(json_file_add_string_vec) #ifdef USE_UCS4 generic,public :: add => json_file_add_string_path_ascii, & json_file_add_string_value_ascii,& json_file_add_string_vec_path_ascii,& json_file_add_string_vec_vec_ascii #endif !> ! Add a null variable to a [[json_file(type)]], by specifying the path. ! generic,public :: add_null => MAYBEWRAP(json_file_add_null), & MAYBEWRAP(json_file_add_null_vec) procedure :: MAYBEWRAP(json_file_add_null) procedure :: MAYBEWRAP(json_file_add_null_vec) !> ! Update a scalar variable in a [[json_file(type)]], ! by specifying the path. ! !@note These have been mostly supplanted by the `add` ! methods, which do a similar thing (and can be used for ! scalars and vectors, etc.) generic,public :: update => MAYBEWRAP(json_file_update_integer), & MAYBEWRAP(json_file_update_logical), & #ifndef REAL32 MAYBEWRAP(json_file_update_real32), & #endif MAYBEWRAP(json_file_update_real), & #ifdef REAL128 MAYBEWRAP(json_file_update_real64), & #endif MAYBEWRAP(json_file_update_string) #ifdef USE_UCS4 generic,public :: update => json_file_update_string_name_ascii, & json_file_update_string_val_ascii #endif !> ! Remove a variable from a [[json_file(type)]] ! by specifying the path. generic,public :: remove => MAYBEWRAP(json_file_remove) !traverse procedure,public :: traverse => json_file_traverse ! hash table functions: procedure,public :: initialize_hash procedure,public :: destroy_hash procedure,public :: is_hash_enabled ! *************************************************** ! operators ! *************************************************** generic,public :: operator(.in.) => MAYBEWRAP(json_file_valid_path_op) procedure,pass(me) :: MAYBEWRAP(json_file_valid_path_op) generic,public :: assignment(=) => assign_json_file,& assign_json_file_to_string,& MAYBEWRAP(assign_string_to_json_file) procedure :: assign_json_file procedure,pass(me) :: assign_json_file_to_string procedure :: MAYBEWRAP(assign_string_to_json_file) ! *************************************************** ! private routines ! *************************************************** !load from string: procedure :: MAYBEWRAP(json_file_load_from_string) !initialize procedure :: initialize_json_core_in_file procedure :: set_json_core_in_file !get info: procedure :: MAYBEWRAP(json_file_variable_info) procedure :: MAYBEWRAP(json_file_variable_matrix_info) !rename: procedure :: MAYBEWRAP(json_file_rename) #ifdef USE_UCS4 procedure :: json_file_rename_path_ascii procedure :: json_file_rename_name_ascii #endif !validate path: procedure :: MAYBEWRAP(json_file_valid_path) !get: procedure :: MAYBEWRAP(json_file_get_object) procedure :: MAYBEWRAP(json_file_get_integer) #ifndef REAL32 procedure :: MAYBEWRAP(json_file_get_real32) #endif procedure :: MAYBEWRAP(json_file_get_real) #ifdef REAL128 procedure :: MAYBEWRAP(json_file_get_real64) #endif procedure :: MAYBEWRAP(json_file_get_logical) procedure :: MAYBEWRAP(json_file_get_string) procedure :: MAYBEWRAP(json_file_get_integer_vec) #ifndef REAL32 procedure :: MAYBEWRAP(json_file_get_real32_vec) #endif procedure :: MAYBEWRAP(json_file_get_real_vec) #ifdef REAL128 procedure :: MAYBEWRAP(json_file_get_real64_vec) #endif procedure :: MAYBEWRAP(json_file_get_logical_vec) procedure :: MAYBEWRAP(json_file_get_string_vec) procedure :: MAYBEWRAP(json_file_get_alloc_string_vec) procedure :: json_file_get_root !add: procedure :: json_file_add procedure :: MAYBEWRAP(json_file_add_object) procedure :: MAYBEWRAP(json_file_add_integer) #ifndef REAL32 procedure :: MAYBEWRAP(json_file_add_real32) #endif procedure :: MAYBEWRAP(json_file_add_real) #ifdef REAL128 procedure :: MAYBEWRAP(json_file_add_real64) #endif procedure :: MAYBEWRAP(json_file_add_logical) procedure :: MAYBEWRAP(json_file_add_string) procedure :: MAYBEWRAP(json_file_add_integer_vec) #ifndef REAL32 procedure :: MAYBEWRAP(json_file_add_real32_vec) #endif procedure :: MAYBEWRAP(json_file_add_real_vec) #ifdef REAL128 procedure :: MAYBEWRAP(json_file_add_real64_vec) #endif procedure :: MAYBEWRAP(json_file_add_logical_vec) procedure :: MAYBEWRAP(json_file_add_string_vec) #ifdef USE_UCS4 procedure :: json_file_add_string_path_ascii procedure :: json_file_add_string_value_ascii procedure :: json_file_add_string_vec_path_ascii procedure :: json_file_add_string_vec_vec_ascii #endif !update: procedure :: MAYBEWRAP(json_file_update_integer) procedure :: MAYBEWRAP(json_file_update_logical) #ifndef REAL32 procedure :: MAYBEWRAP(json_file_update_real32) #endif procedure :: MAYBEWRAP(json_file_update_real) #ifdef REAL128 procedure :: MAYBEWRAP(json_file_update_real64) #endif procedure :: MAYBEWRAP(json_file_update_string) #ifdef USE_UCS4 procedure :: json_file_update_string_name_ascii procedure :: json_file_update_string_val_ascii #endif !remove: procedure :: MAYBEWRAP(json_file_remove) !print: procedure :: json_file_print_to_console procedure :: json_file_print_to_unit procedure :: json_file_print_to_filename final :: finalize_json_file end type json_file !********************************************************* !********************************************************* !> author: Izaak Beekman ! date: 07/23/2015 ! ! Structure constructor to initialize a [[json_file(type)]] ! object with an existing [[json_value]] object or a JSON ! string, and either the [[json_core(type)]] settings or a ! [[json_core(type)]] instance. ! !### Example ! !```fortran ! ... ! type(json_file) :: my_file ! type(json_value),pointer :: json_object ! type(json_core) :: json_core_object ! ... ! ! Construct a json_object: ! !could do this: ! my_file = json_file(json_object) ! !or: ! my_file = json_file(json_object,verbose=.true.) ! !or: ! my_file = json_file('{"x": [1]}',verbose=.true.) ! !or: ! my_file = json_file(json_object,json_core_object) ! !or: ! my_file = json_file('{"x": [1]}',json_core_object) !``` interface json_file module procedure initialize_json_file, & initialize_json_file_v2, & MAYBEWRAP(initialize_json_file_from_string), & MAYBEWRAP(initialize_json_file_from_string_v2) end interface !************************************************************************************* contains !***************************************************************************************** !***************************************************************************************** !> ! Finalizer for [[json_file]] class. ! ! Just a wrapper for [[json_file_destroy]]. subroutine finalize_json_file(me) implicit none type(json_file),intent(inout) :: me call me%destroy(destroy_core=.true.) end subroutine finalize_json_file !***************************************************************************************** !***************************************************************************************** !> ! Check error status in the file. pure function json_file_failed(me) result(failed) implicit none class(json_file),intent(in) :: me logical(LK) :: failed !! will be true if there has been an error. failed = me%core%failed() end function json_file_failed !***************************************************************************************** !***************************************************************************************** !> ! Retrieve error status and message from the class. subroutine json_file_check_for_errors(me,status_ok,error_msg) implicit none class(json_file),intent(inout) :: me 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) if (present(error_msg)) call move_alloc(tmp, error_msg) #else call me%core%check_for_errors(status_ok,error_msg) #endif end subroutine json_file_check_for_errors !***************************************************************************************** !***************************************************************************************** !> ! Clear exceptions in the class. pure subroutine json_file_clear_exceptions(me) implicit none class(json_file),intent(inout) :: me call me%core%clear_exceptions() end subroutine json_file_clear_exceptions !***************************************************************************************** !***************************************************************************************** !> ! This is a wrapper for [[json_print_error_message]]. subroutine json_file_print_error_message(me,io_unit) implicit none class(json_file),intent(inout) :: me integer, intent(in), optional :: io_unit call me%core%print_error_message(io_unit) end subroutine json_file_print_error_message !***************************************************************************************** !***************************************************************************************** !> ! Initialize the [[json_core(type)]] for this [[json_file]]. ! This is just a wrapper for [[json_initialize]]. ! !@note This does not destroy the data in the file. ! !@note [[initialize_json_core]], [[json_initialize]], ! [[initialize_json_core_in_file]], [[initialize_json_file]], ! [[initialize_json_file_v2]], [[initialize_json_file_from_string]], ! and [[initialize_json_file_from_string_v2]] ! all have a similar interface. subroutine initialize_json_core_in_file(me,& #include "json_initialize_dummy_arguments.inc" ) implicit none class(json_file),intent(inout) :: me #include "json_initialize_arguments.inc" call me%core%initialize(& #include "json_initialize_dummy_arguments.inc" ) end subroutine initialize_json_core_in_file !***************************************************************************************** !***************************************************************************************** !> ! Set the [[json_core(type)]] for this [[json_file]]. ! !@note This does not destroy the data in the file. ! !@note This one is used if you want to initialize the file with ! an already-existing [[json_core(type)]] (presumably, this was already ! initialized by a call to [[initialize_json_core]] or similar). subroutine set_json_core_in_file(me,core) implicit none class(json_file),intent(inout) :: me type(json_core),intent(in) :: core me%core = core end subroutine set_json_core_in_file !***************************************************************************************** !***************************************************************************************** !> ! Get a copy of the [[json_core(type)]] in this [[json_file]]. subroutine get_json_core_in_file(me,core) implicit none class(json_file),intent(in) :: me type(json_core),intent(out) :: core core = me%core end subroutine get_json_core_in_file !***************************************************************************************** !***************************************************************************************** !> author: Izaak Beekman ! date: 07/23/2015 ! ! Cast a [[json_value]] object as a [[json_file(type)]] object. ! It also calls the `initialize()` method. ! !@note [[initialize_json_core]], [[json_initialize]], ! [[initialize_json_core_in_file]], [[initialize_json_file]], ! [[initialize_json_file_v2]], [[initialize_json_file_from_string]], ! and [[initialize_json_file_from_string_v2]] ! all have a similar interface. function initialize_json_file(p,& #include "json_initialize_dummy_arguments.inc" , nullify_pointer & ) result(file_object) implicit none type(json_file) :: file_object type(json_value),pointer,optional :: p !! `json_value` object to cast !! as a `json_file` object. This !! will be nullified. #include "json_initialize_arguments.inc" logical(LK),intent(in),optional :: nullify_pointer !! if True, then `p` will be nullified !! if present. (default is True). Normally, !! this should be done, because the [[json_file]] will destroy !! the pointer when the class goes out of scope (causing `p` to be !! a dangling pointer). However, if the intent is to use `p` in !! a [[json_file]] and then call [[json_file:nullify]] and continue !! to use `p`, then this should be set to False. call file_object%initialize(& #include "json_initialize_dummy_arguments.inc" ) if (present(p)) then file_object%p => p ! we have to nullify it to avoid ! a dangling pointer when the file ! goes out of scope if (present(nullify_pointer)) then if (nullify_pointer) nullify(p) else nullify(p) end if end if end function initialize_json_file !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 4/26/2016 ! ! Cast a [[json_value]] pointer and a [[json_core(type)]] object ! as a [[json_file(type)]] object. function initialize_json_file_v2(json_value_object,json_core_object) & result(file_object) implicit none type(json_file) :: file_object type(json_value),pointer,intent(in) :: json_value_object type(json_core),intent(in) :: json_core_object file_object%p => json_value_object file_object%core = json_core_object end function initialize_json_file_v2 !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 01/19/2019 ! ! Cast a JSON string as a [[json_file(type)]] object. ! It also calls the `initialize()` method. ! !### Example ! !```fortran ! type(json_file) :: f ! f = json_file('{"key ": 1}', trailing_spaces_significant=.true.) !``` ! !@note [[initialize_json_core]], [[json_initialize]], ! [[initialize_json_core_in_file]], [[initialize_json_file]], ! [[initialize_json_file_v2]], [[initialize_json_file_from_string]], ! and [[initialize_json_file_from_string_v2]] ! all have a similar interface. function initialize_json_file_from_string(str,& #include "json_initialize_dummy_arguments.inc" ) result(file_object) implicit none type(json_file) :: file_object character(kind=CK,len=*),intent(in) :: str !! string to load JSON data from #include "json_initialize_arguments.inc" call file_object%initialize(& #include "json_initialize_dummy_arguments.inc" ) call file_object%deserialize(str) end function initialize_json_file_from_string !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[initialize_json_file_from_string]], where "str" is kind=CDK. function wrap_initialize_json_file_from_string(str,& #include "json_initialize_dummy_arguments.inc" ) result(file_object) implicit none type(json_file) :: file_object character(kind=CDK,len=*),intent(in) :: str !! string to load JSON data from #include "json_initialize_arguments.inc" file_object = initialize_json_file_from_string(& to_unicode(str),& #include "json_initialize_dummy_arguments.inc" ) end function wrap_initialize_json_file_from_string !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/19/2019 ! ! Cast a JSON string and a [[json_core(type)]] object ! as a [[json_file(type)]] object. function initialize_json_file_from_string_v2(str, json_core_object) & result(file_object) implicit none type(json_file) :: file_object character(kind=CK,len=*),intent(in) :: str !! string to load JSON data from type(json_core),intent(in) :: json_core_object file_object%core = json_core_object call file_object%deserialize(str) end function initialize_json_file_from_string_v2 !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[initialize_json_file_from_string_v2]], where "str" is kind=CDK. function wrap_initialize_json_file_from_string_v2(str,json_core_object) & result(file_object) implicit none type(json_file) :: file_object character(kind=CDK,len=*),intent(in) :: str !! string to load JSON data from type(json_core),intent(in) :: json_core_object file_object = initialize_json_file_from_string_v2(to_unicode(str),json_core_object) end function wrap_initialize_json_file_from_string_v2 !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Nullify the [[json_value]] pointer in a [[json_file(type)]], ! but do not destroy it. ! ! This should normally only be done if the pointer is the target of ! another pointer outside the class that is still intended to be in ! scope after the [[json_file(type)]] has gone out of scope. ! Otherwise, this would result in a memory leak. ! !### See also ! * [[json_file_destroy]] ! !### History ! * 6/30/2019 : Created subroutine json_file_nullify(me) implicit none class(json_file),intent(inout) :: me nullify(me%p) end subroutine json_file_nullify !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Destroy the [[json_value]] data in a [[json_file(type)]]. ! This may be done when the variable is no longer needed, ! or will be reused to open a different file. ! Otherwise a memory leak will occur. ! ! Optionally, also destroy the [[json_core(type)]] instance (this ! is not necessary to prevent memory leaks, since a [[json_core(type)]] ! does not use pointers). ! !### See also ! * [[json_file_nullify]] ! !### History ! * 12/9/2013 : Created ! * 4/26/2016 : Added optional `destroy_core` argument ! * 6/7/2026 : Also destroy hash table. ! !@note This routine will be called automatically when the variable ! goes out of scope. subroutine json_file_destroy(me,destroy_core) implicit none class(json_file),intent(inout) :: me logical,intent(in),optional :: destroy_core !! to also destroy the [[json_core(type)]]. !! default is to leave it as is. if (associated(me%p)) call me%core%destroy(me%p) call me%destroy_hash() ! also have to destroy the hash table if used if (present(destroy_core)) then if (destroy_core) call me%core%destroy() end if end subroutine json_file_destroy !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 12/5/2014 ! ! Move the [[json_value]] pointer from one [[json_file(type)]] to another. ! The "from" pointer is then nullified, but not destroyed. ! !@note If "from%p" is not associated, then an error is thrown. subroutine json_file_move_pointer(to,from) implicit none class(json_file),intent(inout) :: to class(json_file),intent(inout) :: from if (associated(from%p)) then if (from%failed()) then !Don't get the data if the FROM file has an !active exception, since it may not be valid. call to%throw_exception(CK_'Error in json_file_move_pointer: '//& 'error exception in FROM file.') else call to%initialize() !initialize and clear any exceptions that may be present to%p => from%p nullify(from%p) end if else call to%throw_exception(CK_'Error in json_file_move_pointer: '//& 'pointer is not associated.') end if end subroutine json_file_move_pointer !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 12/9/2013 ! ! Load the JSON data from a file. ! !### Example ! !```fortran ! program main ! use json_module ! implicit none ! type(json_file) :: f ! call f%load('my_file.json') ! !... ! call f%destroy() ! end program main !``` subroutine json_file_load(me, filename, unit, destroy_pointer) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: filename !! the filename to open integer(IK),intent(in),optional :: unit !! the unit number to use !! (if not present, a newunit !! is used) logical(LK),intent(in),optional :: destroy_pointer !! destroy the pointer before !! loading (default is True) if (present(destroy_pointer)) then if (destroy_pointer) call me%destroy() else ! by default it is destroyed call me%destroy() end if call me%core%load(file=filename, p=me%p, unit=unit) end subroutine json_file_load !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/13/2015 ! ! Load the JSON data from a string. ! !### Example ! ! Load JSON from a string: !```fortran ! type(json_file) :: f ! call f%deserialize('{ "name": "Leonidas" }') !``` subroutine json_file_load_from_string(me, str, destroy_pointer) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: str !! string to load JSON data from logical(LK),intent(in),optional :: destroy_pointer !! destroy the pointer before !! loading (default is True) if (present(destroy_pointer)) then if (destroy_pointer) call me%destroy() else ! by default it is destroyed call me%destroy() end if call me%core%deserialize(me%p, str) end subroutine json_file_load_from_string !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_load_from_string]], where "str" is kind=CDK. subroutine wrap_json_file_load_from_string(me, str) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: str call me%deserialize(to_unicode(str)) end subroutine wrap_json_file_load_from_string !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/11/2015 ! ! Print the JSON file to the console. subroutine json_file_print_to_console(me) implicit none class(json_file),intent(inout) :: me call me%core%print(me%p,iunit=int(output_unit,IK)) end subroutine json_file_print_to_console !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 12/9/2013 ! ! Prints the JSON file to the specified file unit number. subroutine json_file_print_to_unit(me, iunit) implicit none class(json_file),intent(inout) :: me integer(IK),intent(in) :: iunit !! file unit number (must not be -1) if (iunit/=unit2str) then call me%core%print(me%p,iunit=iunit) else call me%throw_exception(CK_'Error in json_file_print_to_unit: iunit must not be -1.') end if end subroutine json_file_print_to_unit !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/11/2015 ! ! Print the JSON structure to the specified filename. ! The file is opened, printed, and then closed. ! !### Example ! Example loading a JSON file, changing a value, and then printing ! result to a new file: !```fortran ! type(json_file) :: f ! logical :: found ! call f%load('my_file.json') !open the original file ! call f%update('version',4,found) !change the value of a variable ! call f%print('my_file_2.json') !save file as new name !``` subroutine json_file_print_to_filename(me,filename) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: filename !! filename to print to call me%core%print(me%p,filename) end subroutine json_file_print_to_filename !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/11/2015 ! ! Print the JSON file to a string. ! !### Example ! ! Open a JSON file, and then print the contents to a string: !```fortran ! type(json_file) :: f ! character(kind=CK,len=:),allocatable :: str ! call f%load('my_file.json') ! call f%serialize(str) !``` subroutine json_file_print_to_string(me,str) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=:),allocatable,intent(out) :: str !! string to print JSON data to call me%core%serialize(me%p,str) end subroutine json_file_print_to_string !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 2/3/2014 ! ! Returns information about a variable in a [[json_file(type)]]. ! !@note If `found` is present, no exceptions will be thrown if an ! error occurs. Otherwise, an exception will be thrown if the ! variable is not found. subroutine json_file_variable_info(me,path,found,var_type,n_children,name) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! path to the variable logical(LK),intent(out),optional :: found !! the variable exists in the structure integer(IK),intent(out),optional :: var_type !! variable type integer(IK),intent(out),optional :: n_children !! number of children character(kind=CK,len=:),allocatable,intent(out),optional :: name !! variable name call me%core%info(me%p,path,found,var_type,n_children,name) end subroutine json_file_variable_info !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_variable_info]], where "path" is kind=CDK. ! !@note If `found` is present, no exceptions will be thrown if an ! error occurs. Otherwise, an exception will be thrown if the ! variable is not found. subroutine wrap_json_file_variable_info(me,path,found,var_type,n_children,name) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path logical(LK),intent(out),optional :: found integer(IK),intent(out),optional :: var_type integer(IK),intent(out),optional :: n_children character(kind=CK,len=:),allocatable,intent(out),optional :: name !! variable name call me%info(to_unicode(path),found,var_type,n_children,name) end subroutine wrap_json_file_variable_info !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 6/26/2016 ! ! Returns matrix information about a variable in a [[json_file(type)]]. ! !@note If `found` is present, no exceptions will be thrown if an ! error occurs. Otherwise, an exception will be thrown if the ! variable is not found. subroutine json_file_variable_matrix_info(me,path,is_matrix,found,& var_type,n_sets,set_size,name) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! path to the variable logical(LK),intent(out) :: is_matrix !! true if it is a valid matrix logical(LK),intent(out),optional :: found !! true if it was found integer(IK),intent(out),optional :: var_type !! variable type of data in !! the matrix (if all elements have !! the same type) integer(IK),intent(out),optional :: n_sets !! number of data sets (i.e., matrix !! rows if using row-major order) integer(IK),intent(out),optional :: set_size !! size of each data set (i.e., matrix !! cols if using row-major order) character(kind=CK,len=:),allocatable,intent(out),optional :: name !! variable name call me%core%matrix_info(me%p,path,is_matrix,found,var_type,n_sets,set_size,name) end subroutine json_file_variable_matrix_info !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_variable_matrix_info]], where "path" is kind=CDK. ! !@note If `found` is present, no exceptions will be thrown if an ! error occurs. Otherwise, an exception will be thrown if the ! variable is not found. subroutine wrap_json_file_variable_matrix_info(me,path,is_matrix,found,& var_type,n_sets,set_size,name) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! path to the variable logical(LK),intent(out) :: is_matrix !! true if it is a valid matrix logical(LK),intent(out),optional :: found !! true if it was found integer(IK),intent(out),optional :: var_type !! variable type of data in !! the matrix (if all elements have !! the same type) integer(IK),intent(out),optional :: n_sets !! number of data sets (i.e., matrix !! rows if using row-major order) integer(IK),intent(out),optional :: set_size !! size of each data set (i.e., matrix !! cols if using row-major order) character(kind=CK,len=:),allocatable,intent(out),optional :: name !! variable name call me%matrix_info(to_unicode(path),is_matrix,found,var_type,n_sets,set_size,name) end subroutine wrap_json_file_variable_matrix_info !***************************************************************************************** !***************************************************************************************** !> author: Izaak Beekman ! date: 7/23/2015 ! ! Get a [[json_value]] pointer to the JSON file root. ! !@note This is equivalent to calling ```[[json_file]]%get('$',p)``` subroutine json_file_get_root(me,p) implicit none class(json_file),intent(inout) :: me type(json_value),pointer,intent(out) :: p !! pointer to the variable p => me%p end subroutine json_file_get_root !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Assignment operator for [[json_core(type)]] = [[json_core(type)]]. ! This will duplicate the [[json_core(type)]] and also ! perform a deep copy of the [[json_value(type)]] data structure. subroutine assign_json_file(me,f) implicit none class(json_file),intent(out) :: me type(json_file),intent(in) :: f me%core = f%core ! no pointers here so OK to copy call me%core%clone(f%p,me%p) end subroutine assign_json_file !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Assignment operator for character = [[json_core(type)]]. ! This is just a wrapper for the [[json_value_to_string]] routine. ! !### Note ! * If an exception is raised or the file contains no data, ! this will return an empty string. subroutine assign_json_file_to_string(str,me) implicit none character(kind=CK,len=:),allocatable,intent(out) :: str class(json_file),intent(in) :: me type(json_core) :: core_copy !! a copy of `core` from `me` if (me%core%failed() .or. .not. associated(me%p)) then str = CK_'' else ! This is sort of a hack. Since `me` has to have `intent(in)` ! for the assignment to work, we need to make a copy of `me%core` ! so we can call the low level routine (since it needs it to ! be `intent(inout)`) because it's possible for this ! function to raise an exception. core_copy = me%core ! copy the parser settings call core_copy%serialize(me%p,str) if (me%core%failed()) str = CK_'' end if end subroutine assign_json_file_to_string !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Assignment operator for [[json_core(type)]] = character. ! This is just a wrapper for the [[json_file_load_from_string]] routine. subroutine assign_string_to_json_file(me,str) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: str if (associated(me%p)) call me%destroy() if (me%core%failed()) call me%core%clear_exceptions() call me%deserialize(str) end subroutine assign_string_to_json_file !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[assign_string_to_json_file]], where "str" is kind=CDK. subroutine wrap_assign_string_to_json_file(me,str) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: str call me%assign_string_to_json_file(to_unicode(str)) end subroutine wrap_assign_string_to_json_file !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! A wrapper for [[json_file_valid_path]] for the `.in.` operator function json_file_valid_path_op(path,me) result(found) implicit none character(kind=CK,len=*),intent(in) :: path !! the path to the variable class(json_file),intent(in) :: me !! the JSON file logical(LK) :: found !! if the variable was found type(json_core) :: core_copy !! a copy of `core` from `me` ! This is sort of a hack. Since `me` has to have `intent(in)` ! for the operator to work, we need to make a copy of `me%core` ! so we can call the low level routine (since it needs it to ! be `intent(inout)`) because it's technically possible for this ! function to raise an exception. This normally should never ! happen here unless the JSON structure is malformed. core_copy = me%core ! copy the settings (need them to know ! how to interpret the path) found = core_copy%valid_path(me%p, path) ! call the low-level routine call core_copy%destroy() ! just in case (but not really necessary) end function json_file_valid_path_op !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_valid_path_op]], where "path" is kind=CDK. function wrap_json_file_valid_path_op(path,me) result(found) implicit none character(kind=CDK,len=*),intent(in) :: path !! the path to the variable class(json_file),intent(in) :: me !! the JSON file logical(LK) :: found !! if the variable was found found = to_unicode(path) .in. me end function wrap_json_file_valid_path_op !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Returns true if the `path` is present in the JSON file. function json_file_valid_path(me,path) result(found) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable logical(LK) :: found !! if the variable was found found = me%core%valid_path(me%p, path) end function json_file_valid_path !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_valid_path]], where "path" is kind=CDK. function wrap_json_file_valid_path(me,path) result(found) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable logical(LK) :: found !! if the variable was found found = me%valid_path(to_unicode(path)) end function wrap_json_file_valid_path !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Rename a variable in a JSON file. subroutine json_file_rename(me,path,name,found) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=*),intent(in) :: name !! the new name logical(LK),intent(out),optional :: found !! if the variable was found call me%core%rename(me%p, path, name, found) end subroutine json_file_rename !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_rename]], where "path" and "name" are kind=CDK. subroutine wrap_json_file_rename(me,path,name,found) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable character(kind=CDK,len=*),intent(in) :: name !! the new name logical(LK),intent(out),optional :: found !! if the variable was found call me%json_file_rename(to_unicode(path),to_unicode(name),found) end subroutine wrap_json_file_rename !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Wrapper for [[json_file_rename]] where "path" is kind=CDK). subroutine json_file_rename_path_ascii(me,path,name,found) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=*),intent(in) :: name !! the new name logical(LK),intent(out),optional :: found !! if the variable was found call me%json_file_rename(to_unicode(path),name,found) end subroutine json_file_rename_path_ascii !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Wrapper for [[json_file_rename]] where "name" is kind=CDK). subroutine json_file_rename_name_ascii(me,path,name,found) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable character(kind=CDK,len=*),intent(in) :: name !! the new name logical(LK),intent(out),optional :: found !! if the variable was found call me%json_file_rename(path,to_unicode(name),found) end subroutine json_file_rename_name_ascii !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 2/3/2014 ! ! Get a [[json_value]] pointer to an object from a JSON file. ! ! If the hash table has been enabled, then it will use that to get the pointer. ! Note that this only will work for the top-level variables, ! since the hash table only stores those. ! Otherwise, it will fall back to the normal method of getting the pointer. subroutine json_file_get_object(me, path, p, found) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable type(json_value),pointer,intent(out) :: p !! pointer to the variable logical(LK),intent(out),optional :: found !! if it was really found if (me%hash_enabled) then call me%hash%get(path, p, found) ! if p is associated, then we know it was found (see hash_table_get) if (associated(p)) return end if ! if not using the hash table, or the key was not found, ! fall back to the normal method: call me%core%get(me%p, path, p, found) end subroutine json_file_get_object !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_object]], where "path" is kind=CDK. subroutine wrap_json_file_get_object(me, path, p, found) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable type(json_value),pointer,intent(out) :: p !! pointer to the variable logical(LK),intent(out),optional :: found !! if it was really found call me%get(to_unicode(path), p, found) end subroutine wrap_json_file_get_object !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 12/9/2013 ! ! Get an integer value from a JSON file. subroutine json_file_get_integer(me, path, val, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable integer(IK),intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found integer(IK),intent(in),optional :: default integer(IK),parameter :: default_if_not_specified = 0_IK character(kind=CK,len=*),parameter :: routine = CK_'json_file_get_integer' #include "json_file_get_scalar_by_path.inc" end subroutine json_file_get_integer !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_integer]], where "path" is kind=CDK. subroutine wrap_json_file_get_integer(me, path, val, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable integer(IK),intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found integer(IK),intent(in),optional :: default call me%get(to_unicode(path), val, found, default) end subroutine wrap_json_file_get_integer !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/20/2014 ! ! Get an integer vector from a JSON file. subroutine json_file_get_integer_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable integer(IK),dimension(:),allocatable,intent(out) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if it was really found integer(IK),dimension(:),intent(in),optional :: default character(kind=CK,len=*),parameter :: routine = CK_'json_file_get_integer_vec' #include "json_file_get_vec_by_path.inc" end subroutine json_file_get_integer_vec !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_integer_vec]], where "path" is kind=CDK. subroutine wrap_json_file_get_integer_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable integer(IK),dimension(:),allocatable,intent(out) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if it was really found integer(IK),dimension(:),intent(in),optional :: default call me%get(to_unicode(path), vec, found, default) end subroutine wrap_json_file_get_integer_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 12/9/2013 ! ! Get a real(RK) variable value from a JSON file. subroutine json_file_get_real (me, path, val, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(RK),intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found real(RK),intent(in),optional :: default real(RK),parameter :: default_if_not_specified = 0.0_RK character(kind=CK,len=*),parameter :: routine = CK_'json_file_get_real' #include "json_file_get_scalar_by_path.inc" end subroutine json_file_get_real !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_real]], where "path" is kind=CDK. subroutine wrap_json_file_get_real (me, path, val, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(RK),intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found real(RK),intent(in),optional :: default call me%get(to_unicode(path), val, found, default) end subroutine wrap_json_file_get_real !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/19/2014 ! ! Get a real(RK) vector from a JSON file. subroutine json_file_get_real_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(RK),dimension(:),allocatable,intent(out) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if it was really found real(RK),dimension(:),intent(in),optional :: default character(kind=CK,len=*),parameter :: routine = CK_'json_file_get_real_vec' #include "json_file_get_vec_by_path.inc" end subroutine json_file_get_real_vec !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_real_vec]], where "path" is kind=CDK. subroutine wrap_json_file_get_real_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(RK),dimension(:),allocatable,intent(out) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if it was really found real(RK),dimension(:),intent(in),optional :: default call me%get(to_unicode(path), vec, found, default) end subroutine wrap_json_file_get_real_vec !***************************************************************************************** #ifndef REAL32 !***************************************************************************************** !> author: Jacob Williams ! date: 1/21/2019 ! ! Alternate version of [[json_file_get_real]] where `val` is `real32`. subroutine json_file_get_real32 (me, path, val, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(real32),intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found real(real32),intent(in),optional :: default real(RK) :: tmp real(RK) :: tmp_default if (present(default)) then tmp_default = real(default,RK) call me%get(path, tmp, found, tmp_default) else call me%get(path, tmp, found) end if val = real(tmp,real32) end subroutine json_file_get_real32 !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_real32]], where "path" is kind=CDK. subroutine wrap_json_file_get_real32 (me, path, val, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(real32),intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found real(real32),intent(in),optional :: default call me%get(to_unicode(path), val, found, default) end subroutine wrap_json_file_get_real32 !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/21/2019 ! ! Alternate version of [[json_file_get_real_vec]] where `vec` is `real32`. subroutine json_file_get_real32_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(real32),dimension(:),allocatable,intent(out) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if it was really found real(real32),dimension(:),intent(in),optional :: default real(RK),dimension(:),allocatable :: tmp real(RK),dimension(:),allocatable :: tmp_default if (present(default)) then tmp_default = real(default,RK) call me%get(path, tmp, found, tmp_default) else call me%get(path, tmp, found) end if if (allocated(tmp)) vec = real(tmp,real32) end subroutine json_file_get_real32_vec !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_real32_vec]], where "path" is kind=CDK. subroutine wrap_json_file_get_real32_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(real32),dimension(:),allocatable,intent(out) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if it was really found real(real32),dimension(:),intent(in),optional :: default call me%get(to_unicode(path), vec, found, default) end subroutine wrap_json_file_get_real32_vec !***************************************************************************************** #endif #ifdef REAL128 !***************************************************************************************** !> author: Jacob Williams ! date: 1/21/2019 ! ! Alternate version of [[json_file_get_real]] where `val` is `real64`. subroutine json_file_get_real64 (me, path, val, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(real64),intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found real(real64),intent(in),optional :: default real(RK) :: tmp real(RK) :: tmp_default if (present(default)) then tmp_default = real(default, RK) call me%get(path, tmp, found, tmp_default) else call me%get(path, tmp, found) end if val = real(tmp,real64) end subroutine json_file_get_real64 !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_real64]], where "path" is kind=CDK. subroutine wrap_json_file_get_real64 (me, path, val, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(real64),intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found real(real64),intent(in),optional :: default call me%get(to_unicode(path), val, found, default) end subroutine wrap_json_file_get_real64 !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/21/2019 ! ! Alternate version of [[json_file_get_real_vec]] where `vec` is `real64`. subroutine json_file_get_real64_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(real64),dimension(:),allocatable,intent(out) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if it was really found real(real64),dimension(:),intent(in),optional :: default real(RK),dimension(:),allocatable :: tmp real(RK),dimension(:),allocatable :: tmp_default if (present(default)) then tmp_default = real(default, RK) call me%get(path, tmp, found, tmp_default) else call me%get(path, tmp, found) end if if (allocated(tmp)) vec = real(tmp,real64) end subroutine json_file_get_real64_vec !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_real64_vec]], where "path" is kind=CDK. subroutine wrap_json_file_get_real64_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(real64),dimension(:),allocatable,intent(out) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if it was really found real(real64),dimension(:),intent(in),optional :: default call me%get(to_unicode(path), vec, found, default) end subroutine wrap_json_file_get_real64_vec !***************************************************************************************** #endif !***************************************************************************************** !> author: Jacob Williams ! date: 12/9/2013 ! ! Get a logical(LK) value from a JSON file. subroutine json_file_get_logical(me,path,val,found,default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable logical(LK),intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found logical(LK),intent(in),optional :: default logical(LK),parameter :: default_if_not_specified = .false. character(kind=CK,len=*),parameter :: routine = CK_'json_file_get_logical' #include "json_file_get_scalar_by_path.inc" end subroutine json_file_get_logical !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_logical]], where "path" is kind=CDK. subroutine wrap_json_file_get_logical(me,path,val,found,default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable logical(LK),intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found logical(LK),intent(in),optional :: default call me%get(to_unicode(path), val, found, default) end subroutine wrap_json_file_get_logical !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/20/2014 ! ! Get a logical(LK) vector from a JSON file. subroutine json_file_get_logical_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable logical(LK),dimension(:),allocatable,intent(out) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if it was really found logical(LK),dimension(:),intent(in),optional :: default character(kind=CK,len=*),parameter :: routine = CK_'json_file_get_logical_vec' #include "json_file_get_vec_by_path.inc" end subroutine json_file_get_logical_vec !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_logical_vec]], where "path" is kind=CDK. subroutine wrap_json_file_get_logical_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable logical(LK),dimension(:),allocatable,intent(out) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if it was really found logical(LK),dimension(:),intent(in),optional :: default call me%get(to_unicode(path), vec, found, default) end subroutine wrap_json_file_get_logical_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 12/9/2013 ! ! Get a character string from a json file. ! The output val is an allocatable character string. subroutine json_file_get_string(me, path, val, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=:),allocatable,intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found character(kind=CK,len=*),intent(in),optional :: default character(kind=CK,len=*),parameter :: default_if_not_specified = CK_'' character(kind=CK,len=*),parameter :: routine = CK_'json_file_get_string' #include "json_file_get_scalar_by_path.inc" end subroutine json_file_get_string !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_string]], where "path" is kind=CDK. subroutine wrap_json_file_get_string(me, path, val, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=:),allocatable,intent(out) :: val !! value logical(LK),intent(out),optional :: found !! if it was really found character(kind=CK,len=*),intent(in),optional :: default call me%get(to_unicode(path), val, found, default) end subroutine wrap_json_file_get_string !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/19/2014 ! ! Get a string vector from a JSON file. subroutine json_file_get_string_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=*),dimension(:),allocatable,intent(out) :: vec !! value vector logical(LK),intent(out),optional :: found !! if it was really found character(kind=CK,len=*),dimension(:),intent(in),optional :: default character(kind=CK,len=*),parameter :: routine = CK_'json_file_get_string_vec' #include "json_file_get_vec_by_path.inc" end subroutine json_file_get_string_vec !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_string_vec]], where "path" is kind=CDK. subroutine wrap_json_file_get_string_vec(me, path, vec, found, default) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=*),dimension(:),allocatable,intent(out) :: vec !! value vector logical(LK),intent(out),optional :: found !! if it was really found character(kind=CK,len=*),dimension(:),intent(in),optional :: default call me%get(to_unicode(path), vec, found, default) end subroutine wrap_json_file_get_string_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 12/17/2016 ! ! Get an (allocatable length) string vector from a JSON file. ! This is just a wrapper for [[json_get_alloc_string_vec_by_path]]. subroutine json_file_get_alloc_string_vec(me, path, vec, ilen, found, default, default_ilen) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=:),dimension(:),allocatable,intent(out) :: vec !! value vector integer(IK),dimension(:),allocatable,intent(out) :: ilen !! the actual length !! of each character !! string in the array logical(LK),intent(out),optional :: found character(kind=CK,len=*),dimension(:),intent(in),optional :: default integer(IK),dimension(:),intent(in),optional :: default_ilen !! the actual !! length of `default` character(kind=CK,len=*),parameter :: routine = CK_'json_file_get_alloc_string_vec' #include "json_file_get_vec_by_path_alloc.inc" end subroutine json_file_get_alloc_string_vec !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_get_alloc_string_vec]], where "path" is kind=CDK. ! This is just a wrapper for [[wrap_json_get_alloc_string_vec_by_path]]. subroutine wrap_json_file_get_alloc_string_vec(me, path, vec, ilen, found, default, default_ilen) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=:),dimension(:),allocatable,intent(out) :: vec !! value vector integer(IK),dimension(:),allocatable,intent(out) :: ilen !! the actual length !! of each character !! string in the array logical(LK),intent(out),optional :: found character(kind=CK,len=*),dimension(:),intent(in),optional :: default integer(IK),dimension(:),intent(in),optional :: default_ilen !! the actual !! length of `default` call me%get(to_unicode(path), vec, ilen, found, default, default_ilen) end subroutine wrap_json_file_get_alloc_string_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Add a [[json_value]] pointer as the root object to a JSON file. ! !### Note ! ! This is mostly equivalent to: !```fortran ! f = [[json_file]](p) !``` ! But without the finalization calls. ! ! And: !```fortran ! if (destroy_original) call [[json_file]]%destroy() ! call [[json_file]]%add('$',p) !``` subroutine json_file_add(me,p,destroy_original) implicit none class(json_file),intent(inout) :: me type(json_value),pointer,intent(in) :: p !! pointer to the variable to add logical(LK),intent(in),optional :: destroy_original !! if the file currently contains !! an associated pointer, it is !! destroyed. [Default is True] logical(LK) :: destroy !! if `me%p` is to be destroyed if (present(destroy_original)) then destroy = destroy_original else destroy = .true. ! default end if if (destroy) call me%destroy() me%p => p end subroutine json_file_add !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Add a [[json_value]] pointer to an object to a JSON file. subroutine json_file_add_object(me,path,p,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable type(json_value),pointer,intent(in) :: p !! pointer to the variable to add logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%core%add_by_path(me%p,path,p,found,was_created) end subroutine json_file_add_object !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_object]], where "path" is kind=CDK. subroutine wrap_json_file_add_object(me,path,p,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable type(json_value),pointer,intent(in) :: p !! pointer to the variable to add logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_object(to_unicode(path),p,found,was_created) end subroutine wrap_json_file_add_object !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Add an integer value to a JSON file. subroutine json_file_add_integer(me,path,val,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable integer(IK),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%core%add_by_path(me%p,path,val,found,was_created) end subroutine json_file_add_integer !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_integer]], where "path" is kind=CDK. subroutine wrap_json_file_add_integer(me,path,val,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable integer(IK),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_integer(to_unicode(path),val,found,was_created) end subroutine wrap_json_file_add_integer !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Add an integer vector to a JSON file. subroutine json_file_add_integer_vec(me,path,vec,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable integer(IK),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%core%add_by_path(me%p,path,vec,found,was_created) end subroutine json_file_add_integer_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_integer_vec]], where "path" is kind=CDK. subroutine wrap_json_file_add_integer_vec(me,path,vec,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable integer(IK),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_integer_vec(to_unicode(path),vec,found,was_created) end subroutine wrap_json_file_add_integer_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Add a real(RK) variable value to a JSON file. subroutine json_file_add_real(me,path,val,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(RK),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%core%add_by_path(me%p,path,val,found,was_created) end subroutine json_file_add_real !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_real]], where "path" is kind=CDK. subroutine wrap_json_file_add_real(me,path,val,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(RK),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_real(to_unicode(path),val,found,was_created) end subroutine wrap_json_file_add_real !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Add a real(RK) vector to a JSON file. subroutine json_file_add_real_vec(me,path,vec,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(RK),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%core%add_by_path(me%p,path,vec,found,was_created) end subroutine json_file_add_real_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_real_vec]], where "path" is kind=CDK. subroutine wrap_json_file_add_real_vec(me,path,vec,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(RK),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_real_vec(to_unicode(path),vec,found,was_created) end subroutine wrap_json_file_add_real_vec !***************************************************************************************** #ifndef REAL32 !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_real]] where `val` is `real32`. subroutine json_file_add_real32(me,path,val,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(real32),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%core%add_by_path(me%p,path,val,found,was_created) end subroutine json_file_add_real32 !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_real32]], where "path" is kind=CDK. subroutine wrap_json_file_add_real32(me,path,val,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(real32),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_real32(to_unicode(path),val,found,was_created) end subroutine wrap_json_file_add_real32 !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_real_vec]] where `vec` is `real32`. subroutine json_file_add_real32_vec(me,path,vec,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(real32),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%core%add_by_path(me%p,path,vec,found,was_created) end subroutine json_file_add_real32_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_real32_vec]], where "path" is kind=CDK. subroutine wrap_json_file_add_real32_vec(me,path,vec,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(real32),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_real32_vec(to_unicode(path),vec,found,was_created) end subroutine wrap_json_file_add_real32_vec !***************************************************************************************** #endif #ifdef REAL128 !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_real]] where `val` is `real64`. subroutine json_file_add_real64(me,path,val,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(real64),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%core%add_by_path(me%p,path,val,found,was_created) end subroutine json_file_add_real64 !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_real64]], where "path" is kind=CDK. subroutine wrap_json_file_add_real64(me,path,val,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(real64),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_real64(to_unicode(path),val,found,was_created) end subroutine wrap_json_file_add_real64 !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_real_vec]] where `vec` is `real64`. subroutine json_file_add_real64_vec(me,path,vec,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable real(real64),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%core%add_by_path(me%p,path,vec,found,was_created) end subroutine json_file_add_real64_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_real64_vec]], where "path" is kind=CDK. subroutine wrap_json_file_add_real64_vec(me,path,vec,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable real(real64),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_real64_vec(to_unicode(path),vec,found,was_created) end subroutine wrap_json_file_add_real64_vec !***************************************************************************************** #endif !***************************************************************************************** !> author: Jacob Williams ! ! Add a logical(LK) value to a JSON file. subroutine json_file_add_logical(me,path,val,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable logical(LK),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%core%add_by_path(me%p,path,val,found,was_created) end subroutine json_file_add_logical !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_logical]], where "path" is kind=CDK. subroutine wrap_json_file_add_logical(me,path,val,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable logical(LK),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_logical(to_unicode(path),val,found,was_created) end subroutine wrap_json_file_add_logical !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Add a logical(LK) vector to a JSON file. subroutine json_file_add_logical_vec(me,path,vec,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable logical(LK),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%core%add_by_path(me%p,path,vec,found,was_created) end subroutine json_file_add_logical_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_logical_vec]], where "path" is kind=CDK. subroutine wrap_json_file_add_logical_vec(me,path,vec,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable logical(LK),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_logical_vec(to_unicode(path),vec,found,was_created) end subroutine wrap_json_file_add_logical_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Add a null value to a JSON file. subroutine json_file_add_null(me,path,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%core%add_null_by_path(me%p,path,found,was_created) end subroutine json_file_add_null !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_null]], where "path" is kind=CDK. subroutine wrap_json_file_add_null(me,path,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_null(to_unicode(path),found,was_created) end subroutine wrap_json_file_add_null !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Add a null vector to a JSON file. subroutine json_file_add_null_vec(me,path,n_values,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable integer(IK),intent(in) :: n_values !! number of nulls to add logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%core%add_null_by_path(me%p,path,n_values,found,was_created) end subroutine json_file_add_null_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_null_vec]], where "path" is kind=CDK. subroutine wrap_json_file_add_null_vec(me,path,n_values,found,was_created) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable integer(IK),intent(in) :: n_values !! number of nulls to add logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created call me%json_file_add_null_vec(to_unicode(path),n_values,found,was_created) end subroutine wrap_json_file_add_null_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Add a character string to a json file. subroutine json_file_add_string(me,path,val,found,was_created,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=*),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for the `val` logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for the `val` !! (note that ADJUSTL is done before TRIM) if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%core%add_by_path(me%p,path,val,found,was_created,trim_str,adjustl_str) end subroutine json_file_add_string !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_string]], where "path" and "val" are kind=CDK. subroutine wrap_json_file_add_string(me,path,val,found,was_created,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable character(kind=CDK,len=*),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for the `val` logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for the `val` !! (note that ADJUSTL is done before TRIM) call me%json_file_add_string(to_unicode(path),to_unicode(val),found,& was_created,trim_str,adjustl_str) end subroutine wrap_json_file_add_string !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Wrapper for [[json_file_add_string]] where "path" is kind=CDK). subroutine json_file_add_string_path_ascii(me,path,val,found,& was_created,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=*),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for the `val` logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for the `val` !! (note that ADJUSTL is done before TRIM) if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%json_file_add_string(to_unicode(path),val,found,& was_created,trim_str,adjustl_str) end subroutine json_file_add_string_path_ascii !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Wrapper for [[json_file_add_string]] where "val" is kind=CDK). subroutine json_file_add_string_value_ascii(me,path,val,found,& was_created,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable character(kind=CDK,len=*),intent(in) :: val !! value logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for the `val` logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for the `val` !! (note that ADJUSTL is done before TRIM) if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%json_file_add_string(path,to_unicode(val),found,& was_created,trim_str,adjustl_str) end subroutine json_file_add_string_value_ascii !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Add a string vector to a JSON file. subroutine json_file_add_string_vec(me,path,vec,found,& was_created,ilen,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=*),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created integer(IK),dimension(:),intent(in),optional :: ilen !! the string lengths of each !! element in `value`. If not present, !! the full `len(value)` string is added !! for each element. logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for each element logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for each element !! (note that ADJUSTL is done before TRIM) if (.not. associated(me%p)) call me%core%create_object(me%p,ck_'') ! create root call me%core%add_by_path(me%p,path,vec,found,was_created,ilen,trim_str,adjustl_str) end subroutine json_file_add_string_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_string_vec]], where "path" and "vec" are kind=CDK. subroutine wrap_json_file_add_string_vec(me,path,vec,found,& was_created,ilen,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable character(kind=CDK,len=*),dimension(:),intent(in):: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created integer(IK),dimension(:),intent(in),optional :: ilen !! the string lengths of each !! element in `value`. If not present, !! the full `len(value)` string is added !! for each element. logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for each element logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for each element !! (note that ADJUSTL is done before TRIM) call me%json_file_add_string_vec(to_unicode(path),to_unicode(vec),found,& was_created,ilen,trim_str,adjustl_str) end subroutine wrap_json_file_add_string_vec !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_string_vec]], where "path" is kind=CDK. subroutine json_file_add_string_vec_path_ascii(me,path,vec,found,& was_created,ilen,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable character(kind=CK,len=*),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created integer(IK),dimension(:),intent(in),optional :: ilen !! the string lengths of each !! element in `value`. If not present, !! the full `len(value)` string is added !! for each element. logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for each element logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for each element !! (note that ADJUSTL is done before TRIM) call me%json_file_add_string_vec(to_unicode(path),vec,found,& was_created,ilen,trim_str,adjustl_str) end subroutine json_file_add_string_vec_path_ascii !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! ! Alternate version of [[json_file_add_string_vec]], where "vec" is kind=CDK. subroutine json_file_add_string_vec_vec_ascii(me,path,vec,found,& was_created,ilen,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable character(kind=CDK,len=*),dimension(:),intent(in) :: vec !! the value vector logical(LK),intent(out),optional :: found !! if the variable was found logical(LK),intent(out),optional :: was_created !! if the variable had to be created integer(IK),dimension(:),intent(in),optional :: ilen !! the string lengths of each !! element in `value`. If not present, !! the full `len(value)` string is added !! for each element. logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for each element logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for each element !! (note that ADJUSTL is done before TRIM) call me%json_file_add_string_vec(path,to_unicode(vec),found,& was_created,ilen,trim_str,adjustl_str) end subroutine json_file_add_string_vec_vec_ascii !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/10/2015 ! ! Given the path string, if the variable is present in the file, ! and is a scalar, then update its value. ! If it is not present, then create it and set its value. ! !### See also ! * [[json_update_integer]] subroutine json_file_update_integer(me,path,val,found) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path integer(IK),intent(in) :: val logical(LK),intent(out) :: found if (.not. me%core%failed()) call me%core%update(me%p,path,val,found) end subroutine json_file_update_integer !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_update_integer]], where "path" is kind=CDK. subroutine wrap_json_file_update_integer(me,path,val,found) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path integer(IK),intent(in) :: val logical(LK),intent(out) :: found call me%update(to_unicode(path),val,found) end subroutine wrap_json_file_update_integer !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/10/2015 ! ! Given the path string, if the variable is present in the file, ! and is a scalar, then update its value. ! If it is not present, then create it and set its value. ! !### See also ! * [[json_update_logical]] subroutine json_file_update_logical(me,path,val,found) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path logical(LK),intent(in) :: val logical(LK),intent(out) :: found if (.not. me%core%failed()) call me%core%update(me%p,path,val,found) end subroutine json_file_update_logical !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_update_logical]], where "path" is kind=CDK. subroutine wrap_json_file_update_logical(me,path,val,found) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path logical(LK),intent(in) :: val logical(LK),intent(out) :: found call me%update(to_unicode(path),val,found) end subroutine wrap_json_file_update_logical !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 1/10/2015 ! ! Given the path string, if the variable is present in the file, ! and is a scalar, then update its value. ! If it is not present, then create it and set its value. subroutine json_file_update_real(me,path,val,found) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path real(RK),intent(in) :: val logical(LK),intent(out) :: found if (.not. me%core%failed()) call me%core%update(me%p,path,val,found) end subroutine json_file_update_real !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_update_real]], where "path" is kind=CDK. subroutine wrap_json_file_update_real(me,path,val,found) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path real(RK),intent(in) :: val logical(LK),intent(out) :: found call me%update(to_unicode(path),val,found) end subroutine wrap_json_file_update_real !***************************************************************************************** #ifndef REAL32 !***************************************************************************************** !> author: Jacob Williams ! date: 1/21/2019 ! ! Alternate version of [[json_file_update_real]] where `val` is `real32`. subroutine json_file_update_real32(me,path,val,found) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path real(real32),intent(in) :: val logical(LK),intent(out) :: found call me%update(path,real(val,RK),found) end subroutine json_file_update_real32 !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_update_real32]], where "path" is kind=CDK. subroutine wrap_json_file_update_real32(me,path,val,found) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path real(real32),intent(in) :: val logical(LK),intent(out) :: found call me%update(to_unicode(path),val,found) end subroutine wrap_json_file_update_real32 !***************************************************************************************** #endif #ifdef REAL128 !***************************************************************************************** !> author: Jacob Williams ! date: 1/21/2019 ! ! Alternate version of [[json_file_update_real]] where `val` is `real64`. subroutine json_file_update_real64(me,path,val,found) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path real(real64),intent(in) :: val logical(LK),intent(out) :: found call me%update(path,real(val,RK),found) end subroutine json_file_update_real64 !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_update_real64]], where "path" is kind=CDK. subroutine wrap_json_file_update_real64(me,path,val,found) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path real(real64),intent(in) :: val logical(LK),intent(out) :: found call me%update(to_unicode(path),val,found) end subroutine wrap_json_file_update_real64 !***************************************************************************************** #endif !***************************************************************************************** !> author: Jacob Williams ! date: 1/10/2015 ! ! Given the path string, if the variable is present in the file, ! and is a scalar, then update its value. ! If it is not present, then create it and set its value. ! !### See also ! * [[json_update_string]] subroutine json_file_update_string(me,path,val,found,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path character(kind=CK,len=*),intent(in) :: val logical(LK),intent(out) :: found logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for the `val` logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for the `val` !! (note that ADJUSTL is done before TRIM) if (.not. me%core%failed()) call me%core%update(me%p,path,val,found,trim_str,adjustl_str) end subroutine json_file_update_string !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_update_string]], where "path" and "val" are kind=CDK. subroutine wrap_json_file_update_string(me,path,val,found,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path character(kind=CDK,len=*),intent(in) :: val logical(LK),intent(out) :: found logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for the `val` logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for the `val` !! (note that ADJUSTL is done before TRIM) call me%update(to_unicode(path),to_unicode(val),found,trim_str,adjustl_str) end subroutine wrap_json_file_update_string !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_update_string]], where "path" is kind=CDK. subroutine json_file_update_string_name_ascii(me,path,val,found,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path character(kind=CK, len=*),intent(in) :: val logical(LK),intent(out) :: found logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for the `val` logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for the `val` !! (note that ADJUSTL is done before TRIM) call me%update(to_unicode(path),val,found,trim_str,adjustl_str) end subroutine json_file_update_string_name_ascii !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_update_string]], where "val" is kind=CDK. subroutine json_file_update_string_val_ascii(me,path,val,found,trim_str,adjustl_str) implicit none class(json_file),intent(inout) :: me character(kind=CK, len=*),intent(in) :: path character(kind=CDK,len=*),intent(in) :: val logical(LK),intent(out) :: found logical(LK),intent(in),optional :: trim_str !! if TRIM() should be called for the `val` logical(LK),intent(in),optional :: adjustl_str !! if ADJUSTL() should be called for the `val` !! (note that ADJUSTL is done before TRIM) call me%update(path,to_unicode(val),found,trim_str,adjustl_str) end subroutine json_file_update_string_val_ascii !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 6/11/2016 ! ! Traverse the JSON structure in the file. ! This routine calls the user-specified [[json_traverse_callback_func]] ! for each element of the structure. subroutine json_file_traverse(me,traverse_callback) implicit none class(json_file),intent(inout) :: me procedure(json_traverse_callback_func) :: traverse_callback call me%core%traverse(me%p,traverse_callback) end subroutine json_file_traverse !***************************************************************************************** !***************************************************************************************** !> author: Jacob Williams ! date: 7/7/2018 ! ! Remove a variable from a JSON file. ! !@note This is just a wrapper to [[json_core:remove_if_present]]. subroutine json_file_remove(me,path) implicit none class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: path !! the path to the variable call me%core%remove_if_present(me%p,path) end subroutine json_file_remove !***************************************************************************************** !***************************************************************************************** !> ! Alternate version of [[json_file_remove]], where "path" is kind=CDK. subroutine wrap_json_file_remove(me,path) implicit none class(json_file),intent(inout) :: me character(kind=CDK,len=*),intent(in) :: path !! the path to the variable call me%remove(to_unicode(path)) end subroutine wrap_json_file_remove !***************************************************************************************** !***************************************************************************************** !> ! Throw an exception. subroutine throw_exception(me,msg,found) class(json_file),intent(inout) :: me character(kind=CK,len=*),intent(in) :: msg !! the error message logical(LK),intent(inout),optional :: found !! if the caller is handling the !! exception with an optimal return !! argument. If so, `json%stop_on_error` !! is ignored. call me%core%throw_exception(msg,found) end subroutine throw_exception !***************************************************************************************** !***************************************************************************************** !> ! Create a hash table from the contents of the JSON file. ! !### Notes ! * This is an optional step that can be taken after reading a JSON file, ! and before doing any lookups. The hash table only applies to the top level ! keys of the JSON structure. If the JSON file contains nested objects, ! then the hash table will not be used for lookups of keys in those nested objects. ! If it also important to note that, if any manipulation of the data is done ! after the hash table is created, it is the caller's responsibility to call ! [[destroy_hash]] and then [[initialize_hash]] to update the hash table. subroutine initialize_hash(me, status_ok, initial_capacity) class(json_file), intent(inout) :: me logical(LK), intent(out) :: status_ok !! true if no problems. integer(IK), intent(in), optional :: initial_capacity !! initial capacity of the hash table (number of buckets). !! If not provided, it will be set based on the number of members !! divided by the load factor to minimize !! the number of resizes needed as members are inserted type(json_core) :: core type(json_value), pointer :: value ! get the JSON core from the file and the pointer to the root value: call me%get_core(core) call me%get(value) ! call the low-level routine: call me%hash%create(core, value, status_ok, initial_capacity) me%hash_enabled = status_ok end subroutine initialize_hash !***************************************************************************************** !***************************************************************************************** !> ! Check if the hash table is enabled. pure function is_hash_enabled(me) result(enabled) class(json_file),intent(in) :: me logical(LK) :: enabled enabled = me%hash_enabled end function is_hash_enabled !***************************************************************************************** !***************************************************************************************** !> ! Destroy the hash table if it exists. subroutine destroy_hash(me) class(json_file), intent(inout) :: me call me%hash%destroy() me%hash_enabled = .false. end subroutine destroy_hash !***************************************************************************************** !***************************************************************************************** !> ! If `found` is present, set it it false. subroutine flag_not_found(found) logical(LK),intent(out),optional :: found if (present(found)) found = .false. end subroutine flag_not_found !***************************************************************************************** !***************************************************************************************** end module json_file_module !*****************************************************************************************