FMS  2024.03
Flexible Modeling System
yaml_parser.F90
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 
20 !> @defgroup yaml_parser_mod yaml_parser_mod
21 !> @ingroup parser
22 !> @brief Routines to use for parsing yaml files
23 
24 !> @file
25 !> @brief File for @ref yaml_parser_mod
26 
27 !> @addtogroup yaml_parser_mod
28 !> @{
29 module yaml_parser_mod
30 
31 #ifdef use_yaml
32 use fms_mod, only: fms_c2f_string
33 use fms_string_utils_mod, only: string_copy
34 use platform_mod
35 use mpp_mod
36 use iso_c_binding
37 
38 implicit none
39 private
40 
41 public :: open_and_parse_file
42 public :: get_num_unique_blocks
43 public :: get_unique_block_ids
44 public :: get_block_name
45 public :: get_num_blocks
46 public :: get_block_ids
47 public :: get_value_from_key
48 public :: get_nkeys
49 public :: get_key_ids
50 public :: get_key_name
51 public :: get_key_value
52 !public :: clean_up
53 !> @}
54 
55 !> @brief Dermine the value of a key from a keyname
56 !> @ingroup yaml_parser_mod
58  module procedure get_value_from_key_0d
59  module procedure get_value_from_key_1d
60 end interface get_value_from_key
61 
62 !! Error codes from open_and_parse_file_wrap
63 integer, parameter :: MISSING_FILE = -1 !< Error code if the yaml file is missing
64 integer, parameter :: PARSER_INIT_ERROR = -2 !< Error code if unable to create a parser object
65 integer, parameter :: INVALID_YAML = -3 !< Error code if unable to parse a yaml file
66 integer, parameter :: SUCCESSFUL = 1 !< "Error" code if the parsing was successful
67 
68 !> @brief c functions binding
69 !> @ingroup yaml_parser_mod
70 interface
71 
72 !> @brief Private c function that opens and parses a yaml file (see yaml_parser_binding.c)
73 !! @return Flag indicating if the read was successful
74 function open_and_parse_file_wrap(filename, file_id) bind(c) &
75  result(error_code)
76  use iso_c_binding, only: c_char, c_int, c_bool
77  character(kind=c_char), intent(in) :: filename(*) !< Filename of the yaml file
78  integer(kind=c_int), intent(out) :: file_id !< File id corresponding to the yaml file that was opened
79  logical(kind=c_int) :: error_code !< Flag indicating the error message (1 if sucessful)
80 end function open_and_parse_file_wrap
81 
82 !> @brief Private c function that checks if a file_id is valid (see yaml_parser_binding.c)
83 !! @return Flag indicating if the file_id is valid
84 function is_valid_file_id(file_id) bind(c) &
85  result(is_valid)
86  use iso_c_binding, only: c_char, c_int, c_bool
87  integer(kind=c_int), intent(in) :: file_id !< File id corresponding to the yaml file that was opened
88  logical(kind=c_bool) :: is_valid !< Flag indicating if the file_id is valid
89 end function is_valid_file_id
90 
91 !> @brief Private c function that gets the number of key-value pairs in a block (see yaml_parser_binding.c)
92 !! @return Number of key-value pairs in this block
93 function get_nkeys_binding(file_id, block_id) bind(c) &
94  result(nkeys)
95  use iso_c_binding, only: c_char, c_int, c_bool
96  integer(kind=c_int), intent(in) :: file_id !< File id corresponding to the yaml file that was opened
97  integer(kind=c_int), intent(in) :: block_id !< Id of the parent_block
98  integer(kind=c_int) :: nkeys
99 end function get_nkeys_binding
100 
101 !> @brief Private c function that gets the ids of the key-value pairs in a block (see yaml_parser_binding.c)
102 subroutine get_key_ids_binding(file_id, block_id, key_ids) bind(c)
103  use iso_c_binding, only: c_char, c_int, c_bool
104  integer(kind=c_int), intent(in) :: file_id !< File id corresponding to the yaml file that was opened
105  integer(kind=c_int), intent(in) :: block_id !< Id of the parent_block
106  integer(kind=c_int), intent(inout) :: key_ids(*) !< Ids of the key-value pairs
107 end subroutine get_key_ids_binding
108 
109 !> @brief Private c function that checks if a key_id is valid (see yaml_parser_binding.c)
110 !! @return Flag indicating if the key_id is valid
111 function is_valid_key_id(file_id, key_id) bind(c) &
112  result(is_valid)
113  use iso_c_binding, only: c_char, c_int, c_bool
114  integer(kind=c_int), intent(in) :: file_id !< File id corresponding to the yaml file that was opened
115  integer(kind=c_int), intent(in) :: key_id !< Key id to check if valid
116  logical(kind=c_bool) :: is_valid !< Flag indicating if the file_id is valid
117 end function is_valid_key_id
118 
119 !> @brief Private c function that get the key from a key_id in a yaml file
120 !! @return Name of the key obtained
121 function get_key(file_id, key_id) bind(c) &
122  result(key_name)
123  use iso_c_binding, only: c_ptr, c_int, c_bool
124  integer(kind=c_int), intent(in) :: file_id !< File id corresponding to the yaml file that was opened
125  integer(kind=c_int), intent(in) :: key_id !< Id of the key-value pair of interest
126  type(c_ptr) :: key_name
127 end function get_key
128 
129 !> @brief Private c function that get the value from a key_id in a yaml file
130 !! @return String containing the value obtained
131 function get_value(file_id, key_id) bind(c) &
132  result(key_value)
133  use iso_c_binding, only: c_ptr, c_int, c_bool
134  integer(kind=c_int), intent(in) :: file_id !< File id corresponding to the yaml file that was opened
135  integer(kind=c_int), intent(in) :: key_id !< Id of the key-value pair of interest
136  type(c_ptr) :: key_value
137 end function get_value
138 
139 !> @brief Private c function that get the block name from a block_id in a yaml file
140 !! @return String containing the value obtained
141 function get_block(file_id, block_id) bind(c) &
142  result(block_name)
143  use iso_c_binding, only: c_ptr, c_int, c_bool
144  integer(kind=c_int), intent(in) :: file_id !< File id corresponding to the yaml file that was opened
145  integer(kind=c_int), intent(in) :: block_id !< Block_id to get the block name for
146 
147  type(c_ptr) :: block_name
148 end function get_block
149 
150 !> @brief Private c function that determines the value of a key in yaml_file (see yaml_parser_binding.c)
151 !! @return c pointer with the value obtained
152 function get_value_from_key_wrap(file_id, block_id, key_name, success) bind(c) &
153  result(key_value2)
154 
155  use iso_c_binding, only: c_ptr, c_char, c_int, c_bool
156  integer(kind=c_int), intent(in) :: file_id !< File id of the yaml file to search
157  integer(kind=c_int), intent(in) :: block_id !< ID corresponding to the block you want the key for
158  character(kind=c_char), intent(in) :: key_name(*) !< Name of the key you want the value for
159  integer(kind=c_int), intent(out) :: success !< Flag indicating if the call was successful
160  type(c_ptr) :: key_value2
161 end function get_value_from_key_wrap
162 
163 !> @brief Private c function that determines the number of blocks with block_name in the yaml file
164 !! (see yaml_parser_binding.c)
165 !! @return Number of blocks with block_name
166 function get_num_blocks_all(file_id, block_name) bind(c) &
167  result(nblocks)
168  use iso_c_binding, only: c_char, c_int, c_bool
169  integer(kind=c_int), intent(in) :: file_id !< File id of the yaml file to search
170  character(kind=c_char), intent(in) :: block_name(*) !< The name of the block you are looking for
171 
172  integer(kind=c_int) :: nblocks
173 end function get_num_blocks_all
174 
175 !> @brief Private c function that determines the number of blocks with block_name that belong to
176 !! a parent block with parent_block_id in the yaml file (see yaml_parser_binding.c)
177 !! @return Number of blocks with block_name
178 function get_num_blocks_child(file_id, block_name, parent_block_id) bind(c) &
179  result(nblocks)
180  use iso_c_binding, only: c_char, c_int, c_bool
181  integer(kind=c_int), intent(in) :: file_id !< File id of the yaml file to search
182  character(kind=c_char), intent(in) :: block_name(*) !< The name of the block you are looking for
183  integer(kind=c_int) :: parent_block_id !< Id of the parent block
184 
185  integer(kind=c_int) :: nblocks
186 end function get_num_blocks_child
187 
188 !> @brief Private c function that gets the the ids of the blocks with block_name in the yaml file
189 !! (see yaml_parser_binding.c)
190 subroutine get_block_ids_all(file_id, block_name, block_ids) bind(c)
191  use iso_c_binding, only: c_char, c_int, c_bool
192  integer(kind=c_int), intent(in) :: file_id !< File id of the yaml file to search
193  character(kind=c_char), intent(in) :: block_name(*) !< The name of the block you are looking for
194  integer(kind=c_int), intent(inout) :: block_ids(*) !< Id of the parent_block
195 end subroutine get_block_ids_all
196 
197 !> @brief Private c function that gets the the ids of the blocks with block_name and that
198 !! belong to a parent block id in the yaml file (see yaml_parser_binding.c)
199 subroutine get_block_ids_child(file_id, block_name, block_ids, parent_block_id) bind(c)
200  use iso_c_binding, only: c_char, c_int, c_bool
201  integer(kind=c_int), intent(in) :: file_id !< File id of the yaml file to search
202  character(kind=c_char), intent(in) :: block_name(*) !< The name of the block you are looking for
203  integer(kind=c_int), intent(inout) :: block_ids(*) !< Id of the parent_block
204  integer(kind=c_int) :: parent_block_id !< Id of the parent block
205 end subroutine get_block_ids_child
206 
207 !> @brief Private c function that checks if a block_id is valid (see yaml_parser_binding.c)
208 !! @return Flag indicating if the block_id is valid
209 function is_valid_block_id(file_id, block_id) bind(c) &
210  result(is_valid)
211  use iso_c_binding, only: c_char, c_int, c_bool
212  integer(kind=c_int), intent(in) :: file_id !< File id corresponding to the yaml file that was opened
213  integer(kind=c_int), intent(in) :: block_id !< Block id to check if valid
214  logical(kind=c_bool) :: is_valid !< Flag indicating if the file_id is valid
215 end function is_valid_block_id
216 
217 !> @brief Private c function that determines the number of unique blocks that belong to
218 !! a parent block with parent_block_id in the yaml file (see yaml_parser_binding.c)
219 !! @return Number of unique blocks
220 function get_num_unique_blocks_bind(file_id, parent_block_id) bind(c) &
221  result(nblocks)
222  use iso_c_binding, only: c_char, c_int, c_bool
223  integer(kind=c_int), intent(in) :: file_id !< File id of the yaml file to search
224  integer(kind=c_int) :: parent_block_id !< Id of the parent block
225 
226  integer(kind=c_int) :: nblocks
227 end function get_num_unique_blocks_bind
228 
229 !> @brief Private c function that gets the the ids of the unique blocks in the yaml file
230 !! (see yaml_parser_binding.c)
231 subroutine get_unique_block_ids_bind(file_id, block_ids, parent_block_id) bind(c)
232  use iso_c_binding, only: c_char, c_int, c_bool, c_ptr
233  integer(kind=c_int), intent(in) :: file_id !< File id corresponding to the yaml file that was opened
234  integer(kind=c_int), intent(inout) :: block_ids(*) !< Id of the parent_block
235  integer(kind=c_int) :: parent_block_id !< Id of the parent block
236 end subroutine get_unique_block_ids_bind
237 end interface
238 
239 !> @addtogroup yaml_parser_mod
240 !> @{
241 contains
242 
243 !> @brief Opens and parses a yaml file
244 !! @return A file id corresponding to the file that was opened
245 function open_and_parse_file(filename) &
246  result(file_id)
247 
248  character(len=*), intent(in) :: filename !< Filename of the yaml file
249  integer :: error_code !< Flag indicating any errors in the parsing or 1 if sucessful
250  logical :: yaml_exists !< Flag indicating whether the yaml exists
251 
252  integer :: file_id
253 
254  inquire(file=trim(filename), exist=yaml_exists)
255  if (.not. yaml_exists) then
256  file_id = 999
257  call mpp_error(note, "The yaml file:"//trim(filename)//" does not exist, hopefully this is your intent!")
258  return
259  end if
260  error_code = open_and_parse_file_wrap(trim(filename)//c_null_char, file_id)
261  call check_error_code(error_code, filename)
262 
263 end function open_and_parse_file
264 
265 !> @brief Checks the error code from a open_and_parse_file_wrap function call
266 subroutine check_error_code(error_code, filename)
267  integer, intent(in) :: error_code
268  character(len=*), intent(in) :: filename
269 
270  select case (error_code)
271  case (successful)
272  return
273  case (missing_file)
274  call mpp_error(fatal, "Error opening the yaml file:"//trim(filename))
275  case (parser_init_error)
276  call mpp_error(fatal, "Error initializing the parser for the file:"//trim(filename))
277  case (invalid_yaml)
278  call mpp_error(fatal, "Error parsing the file:"//trim(filename)//". Check that your yaml file is valid")
279  end select
280 end subroutine check_error_code
281 
282 !> @brief Gets the key from a file id
283 subroutine get_key_name(file_id, key_id, key_name)
284  integer, intent(in) :: key_id !< Id of the key-value pair of interest
285  integer, intent(in) :: file_id !< File id of the yaml file to search
286  character(len=*), intent(out) :: key_name
287 
288  if (.not. is_valid_file_id(file_id)) call mpp_error(fatal, &
289  & "The file id in your get_key_name call is invalid! Check your call.")
290  if (.not. is_valid_key_id(file_id, key_id)) call mpp_error(fatal, &
291  & "The key id in your get_key_name call is invalid! Check your call.")
292 
293  key_name = fms_c2f_string(get_key(file_id, key_id))
294 
295 end subroutine get_key_name
296 
297 !> @brief Gets the value from a file id
298 subroutine get_key_value(file_id, key_id, key_value)
299  integer, intent(in) :: key_id !< Id of the key-value pair of interest
300  integer, intent(in) :: file_id !< File id of the yaml file to search
301  character(len=*), intent(out) :: key_value
302 
303  if (.not. is_valid_file_id(file_id)) call mpp_error(fatal, &
304  & "The file id in your get_key_value call is invalid! Check your call.")
305  if (.not. is_valid_key_id(file_id, key_id)) call mpp_error(fatal, &
306  & "The key id in your get_key_value call is invalid! Check your call.")
307 
308  key_value = fms_c2f_string(get_value(file_id, key_id))
309 
310 end subroutine get_key_value
311 
312 !> @brief Used to dermine the value of a key from a keyname
313 subroutine get_value_from_key_0d(file_id, block_id, key_name, key_value, is_optional)
314  integer, intent(in) :: file_id !< File id of the yaml file to search
315  integer, intent(in) :: block_id !< ID corresponding to the block you want the key for
316  character(len=*), intent(in) :: key_name !< Name of the key you want the value for
317  class(*), intent(inout):: key_value !< Value of the key
318  logical, intent(in), optional :: is_optional !< Flag indicating if it is okay for the key to not exist.
319  !! If the key does not exist key_value will not be set, so it
320  !! is the user's responsibility to initialize it before the call
321 
322  character(len=255) :: buffer !< String buffer with the value
323 
324  type(c_ptr) :: c_buffer !< c pointer with the value
325  integer(kind=c_int) :: success !< Flag indicating if the value was obtained successfully
326  logical :: optional_flag !< Flag indicating that the key was optional
327  integer :: err_unit !< integer with io error
328 
329  optional_flag = .false.
330  if (present(is_optional)) optional_flag = is_optional
331 
332  if (.not. is_valid_file_id(file_id)) call mpp_error(fatal, &
333  & "The file id in your get_value_from_key call is invalid! Check your call.")
334  if (.not. is_valid_block_id(file_id, block_id)) call mpp_error(fatal, &
335  & "The block id in your get_value_from_key call is invalid! Check your call.")
336 
337  c_buffer = get_value_from_key_wrap(file_id, block_id, trim(key_name)//c_null_char, success)
338  if (success == 1) then
339  buffer = fms_c2f_string(c_buffer)
340 
341  select type (key_value)
342  type is (integer(kind=i4_kind))
343  read(buffer,*, iostat=err_unit) key_value
344  if (err_unit .ne. 0) call mpp_error(fatal, "Key:"// &
345  & trim(key_name)//" Error converting '"//trim(buffer)//"' to i4")
346  type is (integer(kind=i8_kind))
347  read(buffer,*, iostat=err_unit) key_value
348  if (err_unit .ne. 0) call mpp_error(fatal, "Key:"// &
349  & trim(key_name)//" Error converting '"//trim(buffer)//"' to i8")
350  type is (real(kind=r4_kind))
351  read(buffer,*, iostat=err_unit) key_value
352  if (err_unit .ne. 0) call mpp_error(fatal, "Key:"// &
353  & trim(key_name)//" Error converting '"//trim(buffer)//"' to r4")
354  type is (real(kind=r8_kind))
355  read(buffer,*, iostat=err_unit) key_value
356  if (err_unit .ne. 0) call mpp_error(fatal, "Key:"// &
357  & trim(key_name)//" Error converting '"//trim(buffer)//"' to r8")
358  type is (character(len=*))
359  call string_copy(key_value, buffer)
360  type is (logical)
361  if (lowercase(trim(buffer)) == "false") then
362  key_value = .false.
363  elseif (lowercase(trim(buffer)) == "true") then
364  key_value = .true.
365  else
366  call mpp_error(fatal, "Key:"//trim(key_name)//" Error converting '"//trim(buffer)//"' to logical")
367  endif
368  class default
369  call mpp_error(fatal, "The type of your buffer in your get_value_from_key call for key "//trim(key_name)//&
370  &" is not supported. Only i4, i8, r4, r8 and strings are supported.")
371  end select
372  else
373  if(.not. optional_flag) call mpp_error(fatal, "Error getting the value for key:"//trim(key_name))
374  endif
375 
376 end subroutine get_value_from_key_0d
377 
378 !> @brief Used' to dermine the 1D value of a key from a keyname
379 subroutine get_value_from_key_1d(file_id, block_id, key_name, key_value, is_optional)
380  integer, intent(in) :: file_id !< File id of the yaml file to search
381  integer, intent(in) :: block_id !< ID corresponding to the block you want the key for
382  character(len=*), intent(in) :: key_name !< Name of the key you want the value for
383  class(*), intent(inout):: key_value(:) !< Value of the key
384  logical, intent(in), optional :: is_optional !< Flag indicating if it is okay for the key' to not exist.
385  !! If the key does not exist key_value will not be set, so it
386  !! is the user's responsibility to initialize it before the call
387 
388  character(len=255) :: buffer !< String buffer with the value
389 
390  type(c_ptr) :: c_buffer !< c pointer with the value
391  integer(kind=c_int) :: success !< Flag indicating if the value was obtained successfully
392  logical :: optional_flag !< Flag indicating that the key was optional
393  integer :: err_unit !< integer with io error
394 
395  optional_flag=.false.
396  if (present(is_optional)) optional_flag = is_optional
397 
398  if (.not. is_valid_file_id(file_id)) call mpp_error(fatal, &
399  & "The file id in your get_value_from_key call is invalid! Check your call.")
400  if (.not. is_valid_block_id(file_id, block_id)) call mpp_error(fatal, &
401  & "The block id in your get_value_from_key call is invalid! Check your call.")
402 
403  c_buffer = get_value_from_key_wrap(file_id, block_id, trim(key_name)//c_null_char, success)
404  if (success == 1) then
405  buffer = fms_c2f_string(c_buffer)
406 
407  select type (key_value)
408  type is (integer(kind=i4_kind))
409  read(buffer,*, iostat=err_unit) key_value
410  if (err_unit .ne. 0) call mpp_error(fatal, "Key:"// &
411  & trim(key_name)//" Error converting '"//trim(buffer)//"' to i4")
412  type is (integer(kind=i8_kind))
413  read(buffer,*, iostat=err_unit) key_value
414  if (err_unit .ne. 0) call mpp_error(fatal, "Key:"// &
415  & trim(key_name)//" Error converting '"//trim(buffer)//"' to i8")
416  type is (real(kind=r4_kind))
417  read(buffer,*, iostat=err_unit) key_value
418  if (err_unit .ne. 0) call mpp_error(fatal, "Key:"// &
419  & trim(key_name)//" Error converting '"//trim(buffer)//"' to r4")
420  type is (real(kind=r8_kind))
421  read(buffer,*, iostat=err_unit) key_value
422  if (err_unit .ne. 0) call mpp_error(fatal, "Key:"// &
423  & trim(key_name)//" Error converting '"//trim(buffer)//"' to r8")
424  type is (character(len=*))
425  call mpp_error(fatal, "get_value_from_key 1d string variables are not supported. Contact developers")
426  class default
427  call mpp_error(fatal, "The type of your buffer in your get_value_from_key call for key "//trim(key_name)//&
428  &" is not supported. Only i4, i8, r4, r8 and strings are supported.")
429  end select
430  else
431  if(.not. optional_flag) call mpp_error(fatal, "Error getting the value for key:"//trim(key_name))
432  endif
433 end subroutine get_value_from_key_1d
434 
435 !> @brief Determines the number of blocks with block_name in the yaml file
436 !! If parent_block_id is present, it only counts those that belong to that block
437 !! @return Number of blocks with block_name
438 function get_num_blocks(file_id, block_name, parent_block_id) &
439  result(nblocks)
440 
441  integer, intent(in) :: file_id !< File id of the yaml file to search
442  character(len=*), intent(in) :: block_name !< The name of the block you are looking for
443  integer, intent(in), optional :: parent_block_id !< Id of the parent block
444  integer :: nblocks
445 
446  if (.not. is_valid_file_id(file_id)) call mpp_error(fatal, &
447  & "The file id in your get_num_blocks call is invalid! Check your call.")
448 
449  if (.not. present(parent_block_id)) then
450  nblocks=get_num_blocks_all(file_id, trim(block_name)//c_null_char)
451  else
452  if (.not. is_valid_block_id(file_id, parent_block_id)) call mpp_error(fatal, &
453  & "The parent_block id in your get_num_blocks call is invalid! Check your call.")
454  nblocks=get_num_blocks_child(file_id, trim(block_name)//c_null_char, parent_block_id)
455  endif
456 end function get_num_blocks
457 
458 !> @brief Gets the the ids of the blocks with block_name in the yaml file
459 !! If parent_block_id is present, it only gets those that belong to that block
460 subroutine get_block_ids(file_id, block_name, block_ids, parent_block_id)
461 
462  integer, intent(in) :: file_id !< File id of the yaml file to search
463  character(len=*), intent(in) :: block_name !< The name of the block you are looking for
464  integer, intent(inout) :: block_ids(:) !< Id of blocks with block_name
465  integer, intent(in), optional :: parent_block_id !< Id of the parent_block
466  integer :: nblocks_id
467  integer :: nblocks
468 
469  if (.not. is_valid_file_id(file_id)) call mpp_error(fatal, &
470  & "The file id in your get_block_ids call is invalid! Check your call.")
471 
472  nblocks_id = size(block_ids)
473  nblocks = get_num_blocks(file_id, block_name, parent_block_id)
474  if (nblocks .ne. nblocks_id) call mpp_error(fatal, "The size of your block_ids array is not correct")
475 
476  if (.not. present(parent_block_id)) then
477  call get_block_ids_all(file_id, trim(block_name)//c_null_char, block_ids)
478  else
479  if (.not. is_valid_block_id(file_id, parent_block_id)) call mpp_error(fatal, &
480  & "The parent_block id in your get_block_ids call is invalid! Check your call.")
481  call get_block_ids_child(file_id, trim(block_name)//c_null_char, block_ids, parent_block_id)
482  endif
483 end subroutine get_block_ids
484 
485 !> @brief Gets the number of key-value pairs in a block
486 !! @return Number of key-value pairs in this block
487 function get_nkeys(file_id, block_id) &
488  result(nkeys)
489  integer, intent(in) :: file_id !< File id corresponding to the yaml file that was opened
490  integer, intent(in) :: block_id !< Id of the parent_block
491  integer :: nkeys
492 
493  if (.not. is_valid_file_id(file_id)) call mpp_error(fatal, &
494  & "The file id in your get_nkeys call is invalid! Check your call.")
495  if (.not. is_valid_block_id(file_id, block_id)) call mpp_error(fatal, &
496  & "The block id in your get_nkeys call is invalid! Check your call.")
497 
498  nkeys = get_nkeys_binding(file_id, block_id)
499 end function get_nkeys
500 
501 !> @brief Gets the ids of the key-value pairs in a block
502 subroutine get_key_ids (file_id, block_id, key_ids)
503  integer, intent(in) :: file_id !< File id corresponding to the yaml file that was opened
504  integer, intent(in) :: block_id !< Id of the parent_block
505  integer, intent(inout) :: key_ids(:) !< Ids of the key-value pairs
506 
507  integer :: nkey_ids !< Size of key_ids
508  integer :: nkeys !< Actual number of keys
509 
510  if (.not. is_valid_file_id(file_id)) call mpp_error(fatal, &
511  & "The file id in your get_key_ids call is invalid! Check your call.")
512  if (.not. is_valid_block_id(file_id, block_id)) call mpp_error(fatal, &
513  & "The block id in your get_key_ids call is invalid! Check your call.")
514 
515  nkey_ids = size(key_ids)
516  nkeys = get_nkeys(file_id, block_id)
517 
518  if (nkeys .ne. nkey_ids) call mpp_error(fatal, "The size of your key_ids array is not correct.")
519 
520  call get_key_ids_binding (file_id, block_id, key_ids)
521 end subroutine get_key_ids
522 
523 !> @brief Gets the number of unique blocks
524 !! @return The number of unique blocks
525 function get_num_unique_blocks(file_id, parent_block_id) &
526  result(nblocks)
527  integer, intent(in) :: file_id !< File id corresponding to the yaml file that was opened
528  integer, intent(in), optional :: parent_block_id !< Id of the parent_block
529  integer :: nblocks
530 
531  if (.not. is_valid_file_id(file_id)) call mpp_error(fatal, &
532  & "The file id in your get_num_unique_blocks call is invalid! Check your call.")
533 
534  if (.not. present(parent_block_id)) then
535  nblocks = get_num_unique_blocks_bind(file_id, 0)
536  else
537  if (.not. is_valid_block_id(file_id, parent_block_id)) call mpp_error(fatal, &
538  & "The parent_block id in your get_block_ids call is invalid! Check your call.")
539  nblocks = get_num_unique_blocks_bind(file_id, parent_block_id)
540  endif
541 end function
542 
543 !> @brief Gets the ids of the unique block ids
544 subroutine get_unique_block_ids(file_id, block_ids, parent_block_id)
545  integer, intent(in) :: file_id !< File id corresponding to the yaml file that was opened
546  integer, intent(inout) :: block_ids(:) !< Ids of each unique block
547  integer, intent(in), optional :: parent_block_id !< Id of the parent_block
548 
549  if (.not. is_valid_file_id(file_id)) call mpp_error(fatal, &
550  & "The file id in your get_num_unique_blocks_ids call is invalid! Check your call.")
551 
552  if (.not. present(parent_block_id)) then
553  call get_unique_block_ids_bind(file_id, block_ids, 0)
554  else
555  if (.not. is_valid_block_id(file_id, parent_block_id)) call mpp_error(fatal, &
556  & "The parent_block id in your get_block_ids call is invalid! Check your call.")
557  call get_unique_block_ids_bind(file_id, block_ids, parent_block_id)
558  endif
559 end subroutine get_unique_block_ids
560 
561 !> @brief Gets the block name form the block id
562 subroutine get_block_name(file_id, block_id, block_name)
563  integer, intent(in) :: file_id !< File id corresponding to the yaml file that was opened
564  integer, intent(in) :: block_id !< Id of the block to get the name from
565  character(len=*), intent(out) :: block_name !< Name of the block
566 
567  block_name = fms_c2f_string(get_block(file_id, block_id))
568 end subroutine
569 #endif
570 end module yaml_parser_mod
571 !> @}
572 ! close documentation grouping
Converts a C string to a Fortran string.
subroutine, public string_copy(dest, source, check_for_null)
Safely copy a string from one buffer to another.
Error handler.
Definition: mpp.F90:382
subroutine get_value_from_key_0d(file_id, block_id, key_name, key_value, is_optional)
Used to dermine the value of a key from a keyname.
integer function, public get_nkeys(file_id, block_id)
Gets the number of key-value pairs in a block.
subroutine, public get_key_name(file_id, key_id, key_name)
Gets the key from a file id.
integer function, public open_and_parse_file(filename)
Opens and parses a yaml file.
subroutine check_error_code(error_code, filename)
Checks the error code from a open_and_parse_file_wrap function call.
subroutine, public get_key_ids(file_id, block_id, key_ids)
Gets the ids of the key-value pairs in a block.
subroutine get_value_from_key_1d(file_id, block_id, key_name, key_value, is_optional)
Used' to dermine the 1D value of a key from a keyname.
subroutine, public get_block_ids(file_id, block_name, block_ids, parent_block_id)
Gets the the ids of the blocks with block_name in the yaml file If parent_block_id is present,...
integer function, public get_num_unique_blocks(file_id, parent_block_id)
Gets the number of unique blocks.
integer function, public get_num_blocks(file_id, block_name, parent_block_id)
Determines the number of blocks with block_name in the yaml file If parent_block_id is present,...
subroutine, public get_unique_block_ids(file_id, block_ids, parent_block_id)
Gets the ids of the unique block ids.
subroutine, public get_block_name(file_id, block_id, block_name)
Gets the block name form the block id.
subroutine, public get_key_value(file_id, key_id, key_value)
Gets the value from a file id.
Dermine the value of a key from a keyname.
Definition: yaml_parser.F90:57
Private c function that gets the the ids of the blocks with block_name in the yaml file (see yaml_par...
Private c function that gets the the ids of the blocks with block_name and that belong to a parent bl...
Private c function that get the block name from a block_id in a yaml file.
Private c function that gets the ids of the key-value pairs in a block (see yaml_parser_binding....
Private c function that get the key from a key_id in a yaml file.
Private c function that gets the number of key-value pairs in a block (see yaml_parser_binding....
Definition: yaml_parser.F90:93
Private c function that determines the number of blocks with block_name in the yaml file (see yaml_pa...
Private c function that determines the number of blocks with block_name that belong to a parent block...
Private c function that determines the number of unique blocks that belong to a parent block with par...
Private c function that gets the the ids of the unique blocks in the yaml file (see yaml_parser_bindi...
Private c function that determines the value of a key in yaml_file (see yaml_parser_binding....
Private c function that get the value from a key_id in a yaml file.
Private c function that checks if a block_id is valid (see yaml_parser_binding.c)
Private c function that checks if a file_id is valid (see yaml_parser_binding.c)
Definition: yaml_parser.F90:84
Private c function that checks if a key_id is valid (see yaml_parser_binding.c)