FMS 2025.01.02-dev
Flexible Modeling System
Loading...
Searching...
No Matches
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!> @{
29module yaml_parser_mod
30
31#ifdef use_yaml
32use fms_mod, only: fms_c2f_string
33use fms_string_utils_mod, only: string_copy
34use platform_mod
35use mpp_mod
36use iso_c_binding
37
38implicit none
39private
40
41public :: open_and_parse_file
42public :: missing_file_error_code
45public :: get_block_name
46public :: get_num_blocks
47public :: get_block_ids
48public :: get_value_from_key
49public :: get_nkeys
50public :: get_key_ids
51public :: get_key_name
52public :: get_key_value
53!public :: clean_up
54!> @}
55
56integer, 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
63end interface get_value_from_key
64
65!! Error codes from open_and_parse_file_wrap
66integer, parameter :: MISSING_FILE = -1 !< Error code if the yaml file is missing
67integer, parameter :: PARSER_INIT_ERROR = -2 !< Error code if unable to create a parser object
68integer, parameter :: INVALID_YAML = -3 !< Error code if unable to parse a yaml file
69integer, parameter :: SUCCESSFUL = 1 !< "Error" code if the parsing was successful
70
71!> @brief c functions binding
72!> @ingroup yaml_parser_mod
73interface
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
77function 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)
83end 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
87function 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
92end 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
96function 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
102end 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)
105subroutine 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
110end 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
114function 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
120end 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
124function 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
130end 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
134function 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
140end 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
144function 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
151end 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
155function 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
164end 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
169function 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
176end 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
181function 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
189end 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)
193subroutine 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
198end 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)
202subroutine 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
208end 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
212function 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
218end 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
223function 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
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)
234subroutine 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
239end subroutine get_unique_block_ids_bind
240end interface
241
242!> @addtogroup yaml_parser_mod
243!> @{
244contains
245
246!> @brief Opens and parses a yaml file
247!! @return A file id corresponding to the file that was opened
248function 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
266end function open_and_parse_file
267
268!> @brief Checks the error code from a open_and_parse_file_wrap function call
269subroutine 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
283end subroutine check_error_code
284
285!> @brief Gets the key from a file id
286subroutine 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
298end subroutine get_key_name
299
300!> @brief Gets the value from a file id
301subroutine 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
313end subroutine get_key_value
314
315!> @brief Used to dermine the value of a key from a keyname
316subroutine 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
379end subroutine get_value_from_key_0d
380
381!> @brief Used' to dermine the 1D value of a key from a keyname
382subroutine 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
436end 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
441function 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
459end 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
463subroutine 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
486end 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
490function 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)
502end function get_nkeys
503
504!> @brief Gets the ids of the key-value pairs in a block
505subroutine 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)
524end subroutine get_key_ids
525
526!> @brief Gets the number of unique blocks
527!! @return The number of unique blocks
528function 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
544end function
545
546!> @brief Gets the ids of the unique block ids
547subroutine 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
562end subroutine get_unique_block_ids
563
564!> @brief Gets the block name form the block id
565subroutine 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))
571end subroutine
572#endif
573end module yaml_parser_mod
574!> @}
575! close documentation grouping
subroutine, public string_copy(dest, source, check_for_null)
Safely copy a string from one buffer to another.
Error handler.
Definition mpp.F90:382
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.
integer function, public get_nkeys(file_id, block_id)
Gets the number of key-value pairs in a block.
subroutine, public get_key_ids(file_id, block_id, key_ids)
Gets the ids of the key-value pairs in a block.
integer function, public get_num_unique_blocks(file_id, parent_block_id)
Gets the number of unique blocks.
integer function, public open_and_parse_file(filename)
Opens and parses a yaml file.
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.
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_key_name(file_id, key_id, key_name)
Gets the key from a file id.
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,...
subroutine check_error_code(error_code, filename)
Checks the error code from a open_and_parse_file_wrap function call.
Dermine the value of a key from a keyname.
Converts a C string to a Fortran string.
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....
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)
Private c function that checks if a key_id is valid (see yaml_parser_binding.c)