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