diff --git a/src/bufr_util.c b/src/bufr_util.c index 251d460a3..1568fe449 100644 --- a/src/bufr_util.c +++ b/src/bufr_util.c @@ -645,3 +645,78 @@ int codes_bufr_extract_headers_malloc(grib_context* c, const char* filename, cod fclose(fp); return GRIB_SUCCESS; } + +int codes_bufr_header_get_string(codes_bufr_header* bh, const char* key, char *val, size_t *len) +{ + static const char* NOT_FOUND = "not_found"; + int isEcmwfLocal = 0; + Assert(bh); + Assert(key); + + isEcmwfLocal = (bh->ecmwfLocalSectionPresent == 1 && bh->bufrHeaderCentre == 98); + + if (strcmp(key, "message_offset")==0) *len = sprintf(val, "%lu", bh->message_offset); + else if (strcmp(key, "offset")==0) *len = sprintf(val, "%lu", bh->message_offset); + else if (strcmp(key, "message_size")==0) *len = sprintf(val, "%lu", bh->message_size); + else if (strcmp(key, "totalLength")==0) *len = sprintf(val, "%lu", bh->message_size); + else if (strcmp(key, "edition")==0) *len = sprintf(val, "%ld", bh->edition); + else if (strcmp(key, "masterTableNumber")==0) *len = sprintf(val, "%ld", bh->masterTableNumber); + else if (strcmp(key, "bufrHeaderSubCentre")==0) *len = sprintf(val, "%ld", bh->bufrHeaderSubCentre); + else if (strcmp(key, "bufrHeaderCentre")==0) *len = sprintf(val, "%ld", bh->bufrHeaderCentre); + else if (strcmp(key, "updateSequenceNumber")==0) *len = sprintf(val, "%ld", bh->updateSequenceNumber); + else if (strcmp(key, "dataCategory")==0) *len = sprintf(val, "%ld", bh->dataCategory); + else if (strcmp(key, "dataSubCategory")==0) *len = sprintf(val, "%ld", bh->dataSubCategory); + else if (strcmp(key, "masterTablesVersionNumber")==0) *len = sprintf(val, "%ld", bh->masterTablesVersionNumber); + else if (strcmp(key, "localTablesVersionNumber")==0) *len = sprintf(val, "%ld", bh->localTablesVersionNumber); + else if (strcmp(key, "typicalYear")==0) *len = sprintf(val, "%ld", bh->typicalYear); + else if (strcmp(key, "typicalMonth")==0) *len = sprintf(val, "%ld", bh->typicalMonth); + else if (strcmp(key, "typicalDay")==0) *len = sprintf(val, "%ld", bh->typicalDay); + else if (strcmp(key, "typicalHour")==0) *len = sprintf(val, "%ld", bh->typicalHour); + else if (strcmp(key, "typicalMinute")==0) *len = sprintf(val, "%ld", bh->typicalMinute); + else if (strcmp(key, "typicalSecond")==0) *len = sprintf(val, "%ld", bh->typicalSecond); + else if (strcmp(key, "typicalDate")==0) *len = sprintf(val, "%06ld", bh->typicalDate); + else if (strcmp(key, "typicalTime")==0) *len = sprintf(val, "%06ld", bh->typicalTime); + else if (strcmp(key, "internationalDataSubCategory")==0) *len = sprintf(val, "%ld", bh->internationalDataSubCategory); + else if (strcmp(key, "localSectionPresent")==0) *len = sprintf(val, "%ld", bh->ecmwfLocalSectionPresent); + + /* Local ECMWF keys. Can be absent so must return NOT_FOUND */ + else if (strcmp(key, "rdbType")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->rdbType); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "oldSubtype")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->oldSubtype); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "ident")==0) { + if (!isEcmwfLocal || bh->ident == NULL || strlen(bh->ident)==0) *len = sprintf(val, NOT_FOUND); + else *len = sprintf(val, "%s", bh->ident); + } + else if (strcmp(key, "localYear")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->localYear); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localMonth")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->localMonth); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localDay")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->localDay); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localHour")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->localHour); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localMinute")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->localMinute); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localSecond")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->localSecond); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "rdbtimeDay")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->rdbtimeDay); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "rdbtimeHour")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->rdbtimeHour); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "rdbtimeMinute")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->rdbtimeMinute); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "rdbtimeSecond")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->rdbtimeSecond); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "rectimeDay")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->rectimeDay); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "rectimeHour")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->rectimeHour); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "rectimeMinute")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->rectimeMinute); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "rectimeSecond")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->rectimeSecond); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "isSatellite")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->isSatellite); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localLongitude1")==0) { if (isEcmwfLocal) *len = sprintf(val, "%g", bh->localLongitude1); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localLatitude1")==0) { if (isEcmwfLocal) *len = sprintf(val, "%g", bh->localLatitude1); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localLongitude2")==0) { if (isEcmwfLocal) *len = sprintf(val, "%g", bh->localLongitude2); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localLatitude2")==0) { if (isEcmwfLocal) *len = sprintf(val, "%g", bh->localLatitude2); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localLatitude")==0) { if (isEcmwfLocal) *len = sprintf(val, "%g", bh->localLatitude); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localLongitude")==0) { if (isEcmwfLocal) *len = sprintf(val, "%g", bh->localLongitude); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "qualityControl")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->qualityControl); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "newSubtype")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->newSubtype); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "daLoop")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->daLoop); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "localNumberOfObservations")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->localNumberOfObservations); else *len = sprintf(val, NOT_FOUND); } + else if (strcmp(key, "satelliteID")==0) { if (isEcmwfLocal) *len = sprintf(val, "%ld", bh->satelliteID); else *len = sprintf(val, NOT_FOUND); } + + else if (strcmp(key, "numberOfSubsets")==0) *len = sprintf(val, "%lu", bh->numberOfSubsets); + else if (strcmp(key, "observedData")==0) *len = sprintf(val, "%ld", bh->observedData); + else if (strcmp(key, "compressedData")==0) *len = sprintf(val, "%ld", bh->compressedData); + else return GRIB_NOT_FOUND; + + return GRIB_SUCCESS; +} diff --git a/src/eccodes.h b/src/eccodes.h index f8c352917..4626593bd 100644 --- a/src/eccodes.h +++ b/src/eccodes.h @@ -1271,6 +1271,7 @@ codes_handle *codes_grib_util_set_spec(codes_handle *h, * returns 0 if OK, integer value on error. */ int codes_bufr_extract_headers_malloc(codes_context* c, const char* filename, codes_bufr_header** result, int* num_messages, int strict_mode); +int codes_bufr_header_get_string(codes_bufr_header* bh, const char* key, char *val, size_t *len); /* --------------------------------------- */ #ifdef __cplusplus diff --git a/src/grib_api.h b/src/grib_api.h index 62a7e1f5d..a4bd58f0f 100644 --- a/src/grib_api.h +++ b/src/grib_api.h @@ -1585,8 +1585,8 @@ typedef struct codes_bufr_header { long typicalHour; long typicalMinute; long typicalSecond; - long typicalDate; // computed key - long typicalTime; // computed key + long typicalDate; /* computed key */ + long typicalTime; /* computed key */ long internationalDataSubCategory; /*BUFR4-specific*/ diff --git a/src/grib_api_prototypes.h b/src/grib_api_prototypes.h index 4da34d75b..6e9fff368 100644 --- a/src/grib_api_prototypes.h +++ b/src/grib_api_prototypes.h @@ -1486,6 +1486,7 @@ int compute_bufr_key_rank(grib_handle *h, grib_string_list *keys, const char *ke char **codes_bufr_copy_data_return_copied_keys(grib_handle *hin, grib_handle *hout, size_t *nkeys, int *err); int codes_bufr_copy_data(grib_handle *hin, grib_handle *hout); int codes_bufr_extract_headers_malloc(grib_context* c, const char* filename, codes_bufr_header** result, int* num_messages, int strict_mode); +int codes_bufr_header_get_string(codes_bufr_header* bh, const char* key, char *val, size_t *len); /* string_util.c */ diff --git a/tests/bufr_extract_headers.c b/tests/bufr_extract_headers.c index f92946015..e2a7e8769 100644 --- a/tests/bufr_extract_headers.c +++ b/tests/bufr_extract_headers.c @@ -9,28 +9,7 @@ */ #include "eccodes.h" - -static const char* not_found = "not_found"; - -static void print_rdb_key(int local, long value) -{ - if (local) printf("%ld ", value); - else printf("%s ", not_found); -} - -static void print_rdb_key_double(int local, double value) -{ - if (local) printf("%g ", value); - else printf("%s ", not_found); -} - -static void print_rdb_ident(int local, const char* value) -{ - if (!local || value == NULL || strlen(value) == 0) - printf("%s ", not_found); - else - printf("%s ", value); -} +#include int main(int argc, char* argv[]) { @@ -40,8 +19,11 @@ int main(int argc, char* argv[]) codes_bufr_header* header_array = NULL; codes_context* c = codes_context_get_default(); const int strict_mode = 1; + const int MAX_KEYS=100; + int requested_print_keys_count = MAX_KEYS; + codes_values requested_print_keys[MAX_KEYS]; - if (argc != 3) return 1; + assert (argc == 3); keys = argv[1]; /* comma-separated like bufr_ls/bufr_get */ filename = argv[2]; @@ -51,71 +33,19 @@ int main(int argc, char* argv[]) printf("ERROR: %s\n",grib_get_error_message(err)); return 1; } - + + /* Mimic the behaviour of bufr_get -f -p keys for testing */ + err = parse_keyval_string(NULL, keys, 0, GRIB_TYPE_UNDEFINED, requested_print_keys, &requested_print_keys_count); + assert(requested_print_keys_count > 0); for (i=0; i < num_messages; ++i) { - codes_bufr_header bh = header_array[i]; - /* - * Mimic the behaviour of bufr_get -f -p keys for testing - */ - const int has_ecmwf_local = (bh.ecmwfLocalSectionPresent == 1 && bh.bufrHeaderCentre == 98); - - if (strstr(keys, "message_offset")) printf("%ld ", bh.message_offset); - if (strstr(keys, "message_size")) printf("%ld ", bh.message_size); - if (strstr(keys, "edition")) printf("%ld ", bh.edition); - if (strstr(keys, "totalLength")) printf("%ld ", bh.message_size); - if (strstr(keys, "masterTableNumber")) printf("%ld ", bh.masterTableNumber); - if (strstr(keys, "bufrHeaderSubCentre")) printf("%ld ", bh.bufrHeaderSubCentre); - if (strstr(keys, "bufrHeaderCentre")) printf("%ld ", bh.bufrHeaderCentre); - if (strstr(keys, "updateSequenceNumber")) printf("%ld ", bh.updateSequenceNumber); - if (strstr(keys, "dataCategory")) printf("%ld ", bh.dataCategory); - if (strstr(keys, "dataSubCategory")) printf("%ld ", bh.dataSubCategory); - if (strstr(keys, "masterTablesVersionNumber")) printf("%ld ", bh.masterTablesVersionNumber); - if (strstr(keys, "localTablesVersionNumber")) printf("%ld ", bh.localTablesVersionNumber); - if (strstr(keys, "typicalYear")) printf("%ld ", bh.typicalYear); - if (strstr(keys, "typicalMonth")) printf("%ld ", bh.typicalMonth); - if (strstr(keys, "typicalDay")) printf("%ld ", bh.typicalDay); - if (strstr(keys, "typicalHour")) printf("%ld ", bh.typicalHour); - if (strstr(keys, "typicalMinute")) printf("%ld ", bh.typicalMinute); - - if (strstr(keys, "typicalDate")) printf("%ld ", bh.typicalDate); - if (strstr(keys, "typicalTime")) printf("%ld ", bh.typicalTime); - - if (strstr(keys, "internationalDataSubCategory")) printf("%ld ", bh.internationalDataSubCategory); - if (strstr(keys, "typicalSecond")) printf("%ld ", bh.typicalSecond); - if (strstr(keys, "localSectionPresent")) printf("%ld ", bh.ecmwfLocalSectionPresent); - - if (strstr(keys, "rdbType")) print_rdb_key(has_ecmwf_local, bh.rdbType); - if (strstr(keys, "oldSubtype")) print_rdb_key(has_ecmwf_local, bh.oldSubtype); - if (strstr(keys, "localYear")) print_rdb_key(has_ecmwf_local, bh.localYear); - if (strstr(keys, "localMonth")) print_rdb_key(has_ecmwf_local, bh.localMonth); - if (strstr(keys, "localDay")) print_rdb_key(has_ecmwf_local, bh.localDay); - if (strstr(keys, "localHour")) print_rdb_key(has_ecmwf_local, bh.localHour); - if (strstr(keys, "localMinute")) print_rdb_key(has_ecmwf_local, bh.localMinute); - if (strstr(keys, "localSecond")) print_rdb_key(has_ecmwf_local, bh.localSecond); - if (strstr(keys, "rdbtimeDay")) print_rdb_key(has_ecmwf_local, bh.rdbtimeDay); - if (strstr(keys, "rdbtimeHour")) print_rdb_key(has_ecmwf_local, bh.rdbtimeHour); - if (strstr(keys, "rdbtimeMinute")) print_rdb_key(has_ecmwf_local, bh.rdbtimeMinute); - if (strstr(keys, "rdbtimeSecond")) print_rdb_key(has_ecmwf_local, bh.rdbtimeSecond); - if (strstr(keys, "rectimeDay")) print_rdb_key(has_ecmwf_local, bh.rectimeDay); - if (strstr(keys, "rectimeHour")) print_rdb_key(has_ecmwf_local, bh.rectimeHour); - if (strstr(keys, "rectimeMinute")) print_rdb_key(has_ecmwf_local, bh.rectimeMinute); - if (strstr(keys, "rectimeSecond")) print_rdb_key(has_ecmwf_local, bh.rectimeSecond); - if (strstr(keys, "qualityControl")) print_rdb_key(has_ecmwf_local, bh.qualityControl); - if (strstr(keys, "newSubtype")) print_rdb_key(has_ecmwf_local, bh.newSubtype); - if (strstr(keys, "daLoop")) print_rdb_key(has_ecmwf_local, bh.daLoop); - - if (strstr(keys, "localLongitude1")) print_rdb_key_double(has_ecmwf_local, bh.localLongitude1); - if (strstr(keys, "localLatitude1")) print_rdb_key_double(has_ecmwf_local, bh.localLatitude1); - if (strstr(keys, "localLongitude2")) print_rdb_key_double(has_ecmwf_local, bh.localLongitude2); - if (strstr(keys, "localLatitude2")) print_rdb_key_double(has_ecmwf_local, bh.localLatitude2); - - if (strstr(keys, "localNumberOfObservations")) printf("%ld ", bh.localNumberOfObservations); - if (strstr(keys, "satelliteID")) printf("%ld ", bh.satelliteID); - if (strstr(keys, "numberOfSubsets")) printf("%ld ", bh.numberOfSubsets); - if (strstr(keys, "observedData")) printf("%ld ", bh.observedData); - if (strstr(keys, "compressedData")) printf("%ld ", bh.compressedData); - - if (strstr(keys, "ident")) print_rdb_ident(has_ecmwf_local, bh.ident); + int j; + for (j=0; j 0); + printf("%s ", value); + } printf("\n"); } diff --git a/tests/bufr_extract_headers.sh b/tests/bufr_extract_headers.sh index ddd79978d..6a1892ce7 100755 --- a/tests/bufr_extract_headers.sh +++ b/tests/bufr_extract_headers.sh @@ -30,10 +30,17 @@ done # Multi-message BUFR input=${data_dir}/bufr/aeolus_wmo_26.bufr -$EXEC ${test_dir}/bufr_extract_headers edition,totalLength,message_offset $input > $temp1 -${tools_dir}/bufr_get -p offset,edition,totalLength $input > $temp2 +KEYS='offset,edition,totalLength' +$EXEC ${test_dir}/bufr_extract_headers $KEYS $input > $temp1 +${tools_dir}/bufr_get -p $KEYS $input > $temp2 diff -w $temp1 $temp2 +# Test local ECMWF keys; should be "not_found" +input=${data_dir}/bufr/synop.bufr +KEYS='localSectionPresent,rdbType,ident,isSatellite,satelliteID' +$EXEC ${test_dir}/bufr_extract_headers $KEYS $input > $temp1 +${tools_dir}/bufr_get -f -p $KEYS $input > $temp2 +diff -w $temp1 $temp2 # BUFRs with localLatitude1, localLongitude1, localLongitude2 etc bufr_files="