From dd6bdb950d33ae98b464cb88dfa9369da40d41af Mon Sep 17 00:00:00 2001 From: shahramn Date: Thu, 5 Dec 2024 20:50:54 +0100 Subject: [PATCH] Add function codes_key_is_computed --- examples/F90/CMakeLists.txt | 2 ++ examples/F90/key_is_computed.f90 | 38 +++++++++++++++++++++++++++++++ examples/F90/key_is_computed.sh | 16 +++++++++++++ fortran/eccodes_f90_tail.f90 | 30 ++++++++++++++++++++++++ fortran/eccodes_visibility.h | 2 +- fortran/grib_api_externals.h | 2 +- fortran/grib_fortran.cc | 14 +++++++++++- fortran/grib_fortran_prototypes.h | 1 + src/codes_util.cc | 12 ++++++++++ src/eccodes.h | 3 +++ src/eccodes_prototypes.h | 1 + tests/grib_keys_iter.cc | 13 +++++++++++ 12 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 examples/F90/key_is_computed.f90 create mode 100755 examples/F90/key_is_computed.sh diff --git a/examples/F90/CMakeLists.txt b/examples/F90/CMakeLists.txt index c98f234df..cde95e77f 100644 --- a/examples/F90/CMakeLists.txt +++ b/examples/F90/CMakeLists.txt @@ -18,6 +18,7 @@ if( HAVE_BUILD_TOOLS ) bufr_ecc-1284 bufr_ecc-1019 get_native_type + key_is_computed grib_ecc-671 ) list( APPEND tests_extra grib_index @@ -81,6 +82,7 @@ else() codes_set_paths codes_f90_misc get_native_type + key_is_computed grib_ecc-671 ) list( APPEND tests_extra grib_index diff --git a/examples/F90/key_is_computed.f90 b/examples/F90/key_is_computed.f90 new file mode 100644 index 000000000..6b047fca8 --- /dev/null +++ b/examples/F90/key_is_computed.f90 @@ -0,0 +1,38 @@ +! (C) Copyright 2005- ECMWF. +! +! This software is licensed under the terms of the Apache Licence Version 2.0 +! which can be obtained at http://www.apache.org/licenses/LICENSECODES_INTERNAL_ERROR.0. +! +! In applying this licence, ECMWF does not waive the privileges and immunities granted to it by +! virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. +! +program key_is_computed + use eccodes + implicit none + integer :: ihandle, is_computed=0 + + CALL codes_grib_new_from_samples(ihandle, "regular_ll_sfc_grib2") + + CALL codes_key_is_computed(ihandle, 'edition', is_computed) + IF (is_computed /= 0) THEN + call codes_check(CODES_INTERNAL_ERROR, 'Error', 'key edition is coded') + END IF + + CALL codes_key_is_computed(ihandle, 'longitudeOfLastGridPoint', is_computed) + IF (is_computed /= 0) THEN + call codes_check(CODES_INTERNAL_ERROR, 'Error', 'key longitudeOfLastGridPoint is coded') + END IF + + CALL codes_key_is_computed(ihandle, 'longitudeOfLastGridPointInDegrees', is_computed) + IF (is_computed /= 1) THEN + call codes_check(CODES_INTERNAL_ERROR, 'Error', 'key longitudeOfLastGridPointInDegrees is computed') + END IF + + CALL codes_key_is_computed(ihandle, 'gridType', is_computed) + IF (is_computed /= 1) THEN + call codes_check(CODES_INTERNAL_ERROR, 'Error', 'key gridType is computed') + END IF + + CALL codes_release(ihandle) + +end program key_is_computed diff --git a/examples/F90/key_is_computed.sh b/examples/F90/key_is_computed.sh new file mode 100755 index 000000000..975cd001f --- /dev/null +++ b/examples/F90/key_is_computed.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# (C) Copyright 2005- ECMWF. +# +# This software is licensed under the terms of the Apache Licence Version 2.0 +# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. +# +# In applying this licence, ECMWF does not waive the privileges and immunities granted to it by +# virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. +# + +. ./include.ctest.sh + +label="f_key_is_computed" + +${examples_dir}/eccodes_f_key_is_computed + diff --git a/fortran/eccodes_f90_tail.f90 b/fortran/eccodes_f90_tail.f90 index 14dad7118..02f176381 100644 --- a/fortran/eccodes_f90_tail.f90 +++ b/fortran/eccodes_f90_tail.f90 @@ -1710,6 +1710,36 @@ call grib_is_defined(msgid, key, is_defined, status) end subroutine codes_is_defined +!!! + !> Check if a key is computed(virtual) or coded + !> + !> In case of error, if the status parameter (optional) is not given, the program will + !> exit with an error message.\n Otherwise the error message can be + !> gathered with @ref codes_get_error_string. + !> + !> @param msgid id of the message loaded in memory + !> @param key key name + !> @param is_computed 0->coded, 1->computed + !> @param status CODES_SUCCESS if OK, integer value on error + subroutine codes_key_is_computed(msgid, key, is_computed, status) + integer(kind=kindOfInt), intent(in) :: msgid + character(len=*), intent(in) :: key + integer(kind=kindOfInt), intent(out) :: is_computed + integer(kind=kindOfInt), optional, intent(out) :: status + integer(kind=kindOfInt) :: iret + + iret = grib_f_key_is_computed(msgid, key, is_computed) + if (iret /= 0) then + call grib_f_write_on_fail(msgid) + end if + if (present(status)) then + status = iret + else + call grib_check(iret, 'key_is_computed', key) + end if + end subroutine codes_key_is_computed +!!! + !> Get the real(4) value of a key from a message. !> !> In case of error, if the status parameter (optional) is not given, the program will diff --git a/fortran/eccodes_visibility.h b/fortran/eccodes_visibility.h index 9e720f1cd..9fe5d46e5 100644 --- a/fortran/eccodes_visibility.h +++ b/fortran/eccodes_visibility.h @@ -1,4 +1,4 @@ -public :: codes_get, codes_set, codes_set_force, codes_grib_get_data, codes_is_missing, codes_is_defined +public :: codes_get, codes_set, codes_set_force, codes_grib_get_data, codes_is_missing, codes_is_defined, codes_key_is_computed public :: codes_open_file, codes_close_file,codes_read_bytes,codes_write_bytes public :: codes_grib_multi_support_on, codes_grib_multi_support_off public :: codes_keys_iterator_new, & diff --git a/fortran/grib_api_externals.h b/fortran/grib_api_externals.h index 496143c1b..feb9896b3 100644 --- a/fortran/grib_api_externals.h +++ b/fortran/grib_api_externals.h @@ -48,7 +48,7 @@ integer, external :: grib_f_get_int, grib_f_get_long,grib_f_get_int_array, & grib_f_get_real4_elements, grib_f_get_real8_elements, & grib_f_get_string,grib_f_get_string_array, & codes_f_bufr_copy_data, & - grib_f_is_missing,grib_f_is_defined + grib_f_is_missing, grib_f_is_defined, grib_f_key_is_computed integer, external :: grib_f_new_from_index, & grib_f_index_new_from_file, & grib_f_index_add_file, & diff --git a/fortran/grib_fortran.cc b/fortran/grib_fortran.cc index 7ea9b6319..1f9af48c6 100644 --- a/fortran/grib_fortran.cc +++ b/fortran/grib_fortran.cc @@ -2223,7 +2223,7 @@ int grib_f_is_missing_(int* gid, char* key,int* isMissing,int len) int err=0; grib_handle *h = get_handle(*gid); char buf[1024]; - if(!h) return GRIB_INVALID_GRIB; + if (!h) return GRIB_INVALID_GRIB; *isMissing=grib_is_missing(h, cast_char(buf,key,len),&err); return err; @@ -2240,6 +2240,18 @@ int grib_f_is_defined_(int* gid, char* key,int* isDefined,int len) return GRIB_SUCCESS; } +/*****************************************************************************/ +int grib_f_key_is_computed_(int* gid, char* key,int* isComputed,int len) +{ + int err = 0; + grib_handle *h = get_handle(*gid); + char buf[1024]; + if (!h) return GRIB_INVALID_GRIB; + + *isComputed = codes_key_is_computed(h, cast_char(buf,key,len), &err); + return err; +} + /*****************************************************************************/ int grib_f_set_real4_(int* gid, char* key, float* val, int len) { diff --git a/fortran/grib_fortran_prototypes.h b/fortran/grib_fortran_prototypes.h index 8fb2f240f..db1b69836 100644 --- a/fortran/grib_fortran_prototypes.h +++ b/fortran/grib_fortran_prototypes.h @@ -327,6 +327,7 @@ int grib_f_datetime_to_julian_(long* year,long* month,long* day, long* hour,long int grib_f_set_string_array_(int* gid, char* key, char* val,int* nvals,int* slen, int len); int codes_f_bufr_keys_iterator_get_name_(int* iterid, char* name, int len); int codes_f_bufr_multi_element_constant_arrays_off_(); +int grib_f_key_is_computed_(int *gid, char *key, int *isComputed, int len); #ifdef __cplusplus diff --git a/src/codes_util.cc b/src/codes_util.cc index bb705b335..0175ecb2f 100644 --- a/src/codes_util.cc +++ b/src/codes_util.cc @@ -545,3 +545,15 @@ int codes_get_features(char* result, size_t* length, int select) *length = actual_length; return GRIB_SUCCESS; } + +// Returns 1 if the key is computed (virtual) and 0 if it is coded +int codes_key_is_computed(const grib_handle* h, const char* key, int* err) +{ + const grib_accessor* acc = grib_find_accessor(h, key); + if (!acc) { + *err = GRIB_NOT_FOUND; + return 0; + } + *err = GRIB_SUCCESS; + return (acc->length_ == 0); +} diff --git a/src/eccodes.h b/src/eccodes.h index 06e440b1e..e1335c884 100644 --- a/src/eccodes.h +++ b/src/eccodes.h @@ -1339,6 +1339,9 @@ int codes_is_missing(const codes_handle* h, const char* key, int* err); Returns a bool i.e. 0 or 1 */ int codes_is_defined(const codes_handle* h, const char* key); +/* Returns 1 if the key is computed (virtual) and 0 if it is coded */ +int codes_key_is_computed(const grib_handle* h, const char* key, int* err); + /* Returns 1 if the BUFR key is in the header and 0 if it is in the data section. The error code is the final argument */ int codes_bufr_key_is_header(const codes_handle* h, const char* key, int* err); diff --git a/src/eccodes_prototypes.h b/src/eccodes_prototypes.h index 3b4602cb1..617f3c207 100644 --- a/src/eccodes_prototypes.h +++ b/src/eccodes_prototypes.h @@ -847,6 +847,7 @@ bool is_sorted_descending(const double arr[], size_t n); int compute_scaled_value_and_scale_factor(double input, int64_t scaled_value_max, int64_t scale_factor_max, int64_t* ret_value, int64_t* ret_factor); int codes_is_feature_enabled(const char* feature); int codes_get_features(char* result, size_t* length, int select); +int codes_key_is_computed(const grib_handle* h, const char* key, int* err); /* grib_util.cc */ diff --git a/tests/grib_keys_iter.cc b/tests/grib_keys_iter.cc index c7b0759b0..0e93fefde 100644 --- a/tests/grib_keys_iter.cc +++ b/tests/grib_keys_iter.cc @@ -65,6 +65,19 @@ int main(int argc, char* argv[]) int e = grib_keys_iterator_get_long(kiter, &lVal, &llen); Assert(!e); Assert(lVal == 1 || lVal == 2); + Assert(codes_key_is_computed(h, name, &e) == 0 && !e); + } + if (STR_EQUAL(name, "gridType")) { + int e = 0; + Assert(codes_key_is_computed(h, name, &e) == 1 && !e); + } + if (STR_EQUAL(name, "longitudeOfLastGridPointInDegrees")) { + int e = 0; + Assert(codes_key_is_computed(h, name, &e) == 1 && !e); + } + if (STR_EQUAL(name, "longitudeOfLastGridPoint")) { + int e = 0; + Assert(codes_key_is_computed(h, name, &e) == 0 && !e); } }