Merge branch 'develop' into hotfix/ECC-1602-performance-optim-ccsds

This commit is contained in:
Shahram Najm 2023-06-15 13:11:39 +01:00
commit 4533d073e9
11 changed files with 229 additions and 97 deletions

View File

@ -3,11 +3,9 @@ How to build and install ecCodes library/tools
Building and installation has been tested on several platforms and with several compilers.
However for some platforms modifications to the installation engine may be required.
If you encounter any problems during the installation procedure please send an e-mail
with your problem to:
Software.Support@ecmwf.int
If you encounter any problems during the installation procedure, please visit our Support Portal:
https://support.ecmwf.int
Installation using CMake
------------------------

View File

@ -67,9 +67,9 @@ To add the Python3 bindings, use pip3 install from PyPI as follows:
For more details, please see:
https://confluence.ecmwf.int/display/ECC/ecCodes+installation
If you encounter any problems please send an e-mail with your problem to:
If you encounter any problems please visit our Support Portal:
Software.Support@ecmwf.int
https://support.ecmwf.int

View File

@ -10,8 +10,8 @@
#include "grib_api_internal.h"
/* Return the rank of the key using list of keys (For BUFR keys) */
/* The argument 'keys' is an input as well as output from each call */
// Return the rank of the key using list of keys (For BUFR keys)
// The argument 'keys' is an input as well as output from each call
int compute_bufr_key_rank(grib_handle* h, grib_string_list* keys, const char* key)
{
grib_string_list* next = keys;
@ -43,11 +43,11 @@ int compute_bufr_key_rank(grib_handle* h, grib_string_list* keys, const char* ke
next->count++;
theRank = next->count;
if (theRank == 1) {
/* If the count is 1 it could mean two things: */
/* This is the first instance of the key and there is another one */
/* This is the first and only instance of the key */
/* So we check if there is a second one of this key, */
/* If not, then rank is zero i.e. this is the only instance */
// If the count is 1 it could mean two things:
// This is the first instance of the key and there is another one
// This is the first and only instance of the key
// So we check if there is a second one of this key,
// If not, then rank is zero i.e. this is the only instance
size_t slen = strlen(key) + 5;
char* s = (char*)grib_context_malloc_clear(c, slen);
snprintf(s, slen, "#2#%s", key);
@ -77,14 +77,13 @@ char** codes_bufr_copy_data_return_copied_keys(grib_handle* hin, grib_handle* ho
while (codes_bufr_keys_iterator_next(kiter)) {
char* name = codes_bufr_keys_iterator_get_name(kiter);
/* if the copy fails we want to keep copying without any errors.
This is because the copy can be between structures that are not
identical and we want to copy what can be copied and skip what
cannot be copied because is not in the output handle
*/
// if the copy fails we want to keep copying without any errors.
// This is because the copy can be between structures that are not
// identical and we want to copy what can be copied and skip what
// cannot be copied because is not in the output handle
*err = codes_copy_key(hin, hout, name, 0);
if (*err == 0) {
/* 'name' will be freed when we call codes_bufr_keys_iterator_delete so copy */
// 'name' will be freed when we call codes_bufr_keys_iterator_delete so copy
char* copied_name = strdup(name);
k = grib_sarray_push(hin->context, k, copied_name);
}
@ -93,7 +92,7 @@ char** codes_bufr_copy_data_return_copied_keys(grib_handle* hin, grib_handle* ho
keys = grib_sarray_get_array(hin->context, k);
grib_sarray_delete(hin->context, k);
if (*nkeys > 0) {
/* Do the pack if something was copied */
// Do the pack if something was copied
*err = grib_set_long(hout, "pack", 1);
}
codes_bufr_keys_iterator_delete(kiter);
@ -116,18 +115,17 @@ int codes_bufr_copy_data(grib_handle* hin, grib_handle* hout)
while (codes_bufr_keys_iterator_next(kiter)) {
char* name = codes_bufr_keys_iterator_get_name(kiter);
/* if the copy fails we want to keep copying without any error messages.
This is because the copy can be between structures that are not
identical and we want to copy what can be copied and skip what
cannot be copied because is not in the output handle
*/
// if the copy fails we want to keep copying without any error messages.
// This is because the copy can be between structures that are not
// identical and we want to copy what can be copied and skip what
// cannot be copied because is not in the output handle
err = codes_copy_key(hin, hout, name, GRIB_TYPE_UNDEFINED);
if (err == 0)
nkeys++;
}
if (nkeys > 0) {
/* Do the pack if something was copied */
// Do the pack if something was copied
err = grib_set_long(hout, "pack", 1);
}
@ -135,7 +133,7 @@ int codes_bufr_copy_data(grib_handle* hin, grib_handle* hout)
return err;
}
#define BUFR_SECTION0_LEN 8 /* BUFR section 0 is always 8 bytes long */
#define BUFR_SECTION0_LEN 8 // BUFR section 0 is always 8 bytes long
static int bufr_extract_edition(const void* message, long* edition)
{
const long nbits_edition = 8;
@ -145,7 +143,7 @@ static int bufr_extract_edition(const void* message, long* edition)
*edition = (long)grib_decode_unsigned_long(pMessage, &pos_edition, nbits_edition);
return GRIB_SUCCESS;
}
/* The ECMWF BUFR local use section */
// The ECMWF BUFR local use section
static int bufr_decode_rdb_keys(const void* message, long offset_section2, codes_bufr_header* hdr)
{
const unsigned char* pMessage = (const unsigned char*)message;
@ -181,7 +179,7 @@ static int bufr_decode_rdb_keys(const void* message, long offset_section2, codes
hdr->localMinute = (long)grib_decode_unsigned_long(p, &start, 6);
hdr->localSecond = (long)grib_decode_unsigned_long(p, &start, 6);
/* rdbtime */
// rdbtime
p = (unsigned char*)message + offset_rdbtime;
start = 0;
hdr->rdbtimeDay = (long)grib_decode_unsigned_long(p, &start, 6);
@ -189,7 +187,7 @@ static int bufr_decode_rdb_keys(const void* message, long offset_section2, codes
hdr->rdbtimeMinute = (long)grib_decode_unsigned_long(p, &start, 6);
hdr->rdbtimeSecond = (long)grib_decode_unsigned_long(p, &start, 6);
/* rectime */
// rectime
p = (unsigned char*)message + offset_rectime;
start = 0;
hdr->rectimeDay = (long)grib_decode_unsigned_long(p, &start, 6);
@ -206,16 +204,16 @@ static int bufr_decode_rdb_keys(const void* message, long offset_section2, codes
return GRIB_SUCCESS;
}
#define IDENT_LEN 9 /* 8 chars plus the final 0 terminator */
#define IDENT_LEN 9 // 8 chars plus the final 0 terminator
/* The ECMWF BUFR local use section */
// The ECMWF BUFR local use section
static int bufr_decode_extra_rdb_keys(const void* message, long offset_section2, codes_bufr_header* hdr)
{
bool isSatelliteType = false;
long start = 0;
const long offset_keyData = offset_section2 + 6;
const long offset_keyMore = offset_section2 + 19; /* 8 bytes long */
const long offset_keySat = offset_section2 + 27; /* 9 bytes long */
const long offset_keyMore = offset_section2 + 19; // 8 bytes long
const long offset_keySat = offset_section2 + 27; // 9 bytes long
unsigned char* pKeyData = (unsigned char*)message + offset_keyData;
char* pKeyMore = (char*)message + offset_keyMore;
@ -233,7 +231,7 @@ static int bufr_decode_extra_rdb_keys(const void* message, long offset_section2,
}
if (hdr->isSatellite) {
unsigned char* pKeyMoreLong = (unsigned char*)message + offset_keyMore; /* as an integer */
unsigned char* pKeyMoreLong = (unsigned char*)message + offset_keyMore; // as an integer
unsigned char* pKeySat = (unsigned char*)message + offset_keySat;
unsigned long lValue = 0;
start = 40;
@ -277,13 +275,13 @@ static int bufr_decode_extra_rdb_keys(const void* message, long offset_section2,
lValue = grib_decode_unsigned_long(pKeyData, &start, 26);
hdr->localLongitude = (lValue - 18000000.0) / 100000.0;
/* interpret keyMore as a string. Copy to a temporary */
// interpret keyMore as a string. Copy to a temporary
for (i = 0; i < IDENT_LEN - 1; ++i) {
temp[i] = *pKeyMore++;
}
temp[i] = '\0';
pTemp = temp;
string_lrtrim(&pTemp, 1, 1); /* Trim left and right */
string_lrtrim(&pTemp, 1, 1); // Trim left and right
strncpy(hdr->ident, pTemp, IDENT_LEN - 1);
}
@ -331,7 +329,7 @@ static int bufr_decode_edition3(const void* message, codes_bufr_header* hdr)
long nbits_localTablesVersionNumber = 1 * 8;
long pos_localTablesVersionNumber = 19 * 8;
const long typicalCentury = 21; /* This century */
const long typicalCentury = 21; // This century
long typicalYearOfCentury = 0;
long nbits_typicalYearOfCentury = 1 * 8;
long pos_typicalYearOfCentury = 20 * 8;
@ -352,11 +350,11 @@ static int bufr_decode_edition3(const void* message, codes_bufr_header* hdr)
long offset_section2 = 0;
long offset_section3 = 0;
long nbits_numberOfSubsets = 2 * 8;
long pos_numberOfSubsets = 0; /*depends on offset_section3*/
long pos_numberOfSubsets = 0; //depends on offset_section3
unsigned long section3Flags;
long nbits_section3Flags = 1 * 8;
long pos_section3Flags = 0; /*depends on offset_section3*/
long pos_section3Flags = 0; //depends on offset_section3
totalLength = grib_decode_unsigned_long(pMessage, &pos_totalLength, nbits_totalLength);
if (totalLength != hdr->message_size) {
@ -383,7 +381,7 @@ static int bufr_decode_edition3(const void* message, codes_bufr_header* hdr)
hdr->typicalDate = hdr->typicalYear * 10000 + hdr->typicalMonth * 100 + hdr->typicalDay;
hdr->typicalTime = hdr->typicalHour * 10000 + hdr->typicalMinute * 100 + hdr->typicalSecond;
offset_section2 = BUFR_SECTION0_LEN + section1Length; /*bytes*/
offset_section2 = BUFR_SECTION0_LEN + section1Length; //bytes
section2Length = 0;
hdr->localSectionPresent = (section1Flags != 0);
if (hdr->localSectionPresent) {
@ -399,7 +397,7 @@ static int bufr_decode_edition3(const void* message, codes_bufr_header* hdr)
}
}
offset_section3 = BUFR_SECTION0_LEN + section1Length + section2Length; /*bytes*/
offset_section3 = BUFR_SECTION0_LEN + section1Length + section2Length; //bytes
pos_numberOfSubsets = (offset_section3 + 4) * 8;
hdr->numberOfSubsets = grib_decode_unsigned_long(pMessage, &pos_numberOfSubsets, nbits_numberOfSubsets);
@ -459,7 +457,7 @@ static int bufr_decode_edition4(const void* message, codes_bufr_header* hdr)
long nbits_localTablesVersionNumber = 1 * 8;
long pos_localTablesVersionNumber = 22 * 8;
long typicalYear2 = 0; /* corrected */
long typicalYear2 = 0; // corrected
long nbits_typicalYear = 2 * 8;
long pos_typicalYear = 23 * 8;
@ -482,11 +480,11 @@ static int bufr_decode_edition4(const void* message, codes_bufr_header* hdr)
long offset_section2 = 0;
long offset_section3 = 0;
long nbits_numberOfSubsets = 2 * 8;
long pos_numberOfSubsets = 0; /*depends on offset_section3*/
long pos_numberOfSubsets = 0; //depends on offset_section3
unsigned long section3Flags;
long nbits_section3Flags = 1 * 8;
long pos_section3Flags = 0; /*depends on offset_section3*/
long pos_section3Flags = 0; //depends on offset_section3
totalLength = grib_decode_unsigned_long(pMessage, &pos_totalLength, nbits_totalLength);
if (totalLength != hdr->message_size) {
@ -505,7 +503,7 @@ static int bufr_decode_edition4(const void* message, codes_bufr_header* hdr)
hdr->localTablesVersionNumber = (long)grib_decode_unsigned_long(pMessage, &pos_localTablesVersionNumber, nbits_localTablesVersionNumber);
hdr->typicalYear = (long)grib_decode_unsigned_long(pMessage, &pos_typicalYear, nbits_typicalYear);
typicalYear2 = hdr->typicalYear < 100 ? 2000 + hdr->typicalYear : hdr->typicalYear; /*ECC-556*/
typicalYear2 = hdr->typicalYear < 100 ? 2000 + hdr->typicalYear : hdr->typicalYear; //ECC-556
hdr->typicalMonth = (long)grib_decode_unsigned_long(pMessage, &pos_typicalMonth, nbits_typicalMonth);
hdr->typicalDay = (long)grib_decode_unsigned_long(pMessage, &pos_typicalDay, nbits_typicalDay);
hdr->typicalHour = (long)grib_decode_unsigned_long(pMessage, &pos_typicalHour, nbits_typicalHour);
@ -514,7 +512,7 @@ static int bufr_decode_edition4(const void* message, codes_bufr_header* hdr)
hdr->typicalDate = typicalYear2 * 10000 + hdr->typicalMonth * 100 + hdr->typicalDay;
hdr->typicalTime = hdr->typicalHour * 10000 + hdr->typicalMinute * 100 + hdr->typicalSecond;
offset_section2 = BUFR_SECTION0_LEN + section1Length; /*bytes*/
offset_section2 = BUFR_SECTION0_LEN + section1Length; //bytes
section2Length = 0;
hdr->localSectionPresent = (section1Flags != 0);
if (hdr->localSectionPresent) {
@ -530,7 +528,7 @@ static int bufr_decode_edition4(const void* message, codes_bufr_header* hdr)
}
}
offset_section3 = BUFR_SECTION0_LEN + section1Length + section2Length; /*bytes*/
offset_section3 = BUFR_SECTION0_LEN + section1Length + section2Length; //bytes
pos_numberOfSubsets = (offset_section3 + 4) * 8;
hdr->numberOfSubsets = grib_decode_unsigned_long(pMessage, &pos_numberOfSubsets, nbits_numberOfSubsets);
@ -584,10 +582,10 @@ static int count_bufr_messages(grib_context* c, FILE* f, int* n, int strict_mode
while (!done) {
mesg = wmo_read_bufr_from_file_malloc(f, 0, &size, &offset, &err);
/*printf("Count so far=%d, mesg=%x, err=%d (%s)\n", *n, mesg, err, grib_get_error_message(err));*/
//printf("Count so far=%d, mesg=%x, err=%d (%s)\n", *n, mesg, err, grib_get_error_message(err));
if (!mesg) {
if (err == GRIB_END_OF_FILE || err == GRIB_PREMATURE_END_OF_FILE) {
done = 1; /* reached the end */
done = 1; // reached the end
break;
}
if (strict_mode)
@ -669,7 +667,7 @@ int codes_bufr_extract_headers_malloc(grib_context* c, const char* filename, cod
}
if (!mesg) {
if (err != GRIB_END_OF_FILE && err != GRIB_PREMATURE_END_OF_FILE) {
/* An error occurred */
// An error occurred
grib_context_log(c, GRIB_LOG_ERROR, "codes_bufr_extract_headers_malloc: Unable to read BUFR message");
if (strict_mode) {
fclose(fp);
@ -786,7 +784,7 @@ static const char* codes_bufr_header_get_centre_name(long edition, long centre_c
}
#if 0
/* TODO: Not efficient as it opens the code table every time */
// TODO: Not efficient as it opens the code table every time
static char* codes_bufr_header_get_centre_name(long edition, long centre_code)
{
char full_path[2014] = {0,};
@ -849,7 +847,7 @@ int codes_bufr_header_get_string(codes_bufr_header* bh, const char* key, char* v
bool isEcmwfLocal = false;
Assert(bh);
Assert(key);
*len = strlen(NOT_FOUND); /*By default*/
*len = strlen(NOT_FOUND); // By default
isEcmwfLocal = (bh->ecmwfLocalSectionPresent == 1);
Assert(!(isEcmwfLocal && bh->bufrHeaderCentre != 98));
@ -913,7 +911,7 @@ int codes_bufr_header_get_string(codes_bufr_header* bh, const char* key, char* v
else if (strcmp(key, "ecmwfLocalSectionPresent") == 0)
*len = snprintf(val, 32, "%ld", bh->ecmwfLocalSectionPresent);
/* Local ECMWF keys. Can be absent so must return NOT_FOUND */
// Local ECMWF keys. Can be absent so must return NOT_FOUND
else if (strcmp(key, "rdbType") == 0) {
if (isEcmwfLocal)
*len = snprintf(val, 32, "%ld", bh->rdbType);
@ -1113,7 +1111,7 @@ int codes_bufr_header_get_string(codes_bufr_header* bh, const char* key, char* v
return GRIB_SUCCESS;
}
/* Returns 1 if the BUFR key is in the header and 0 if it is in the data section */
// Returns 1 if the BUFR key is in the header and 0 if it is in the data section
int codes_bufr_key_is_header(const grib_handle* h, const char* key, int* err)
{
grib_accessor* acc = grib_find_accessor(h, key);
@ -1121,5 +1119,18 @@ int codes_bufr_key_is_header(const grib_handle* h, const char* key, int* err)
*err = GRIB_NOT_FOUND;
return 0;
}
*err = GRIB_SUCCESS;
return ((acc->flags & GRIB_ACCESSOR_FLAG_BUFR_DATA) == 0);
}
// Returns 1 if the BUFR key is a coordinate descriptor
int codes_bufr_key_is_coordinate(const grib_handle* h, const char* key, int* err)
{
grib_accessor* acc = grib_find_accessor(h, key);
if (!acc) {
*err = GRIB_NOT_FOUND;
return 0;
}
*err = GRIB_SUCCESS;
return ((acc->flags & GRIB_ACCESSOR_FLAG_BUFR_COORD) != 0);
}

View File

@ -1360,6 +1360,10 @@ int codes_is_defined(const codes_handle* h, const char* key);
The error code is the final argument */
int codes_bufr_key_is_header(const codes_handle* h, const char* key, int* err);
/* Returns 1 if the BUFR key is a coordinate descriptor and 0 otherwise.
The error code is the final argument */
int codes_bufr_key_is_coordinate(const codes_handle* h, const char* key, int* err);
int codes_set_missing(codes_handle* h, const char* key);
/* The truncation is the Gaussian number (or order) */
int codes_get_gaussian_latitudes(long truncation, double* latitudes);

View File

@ -1479,6 +1479,7 @@ 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);
int codes_bufr_key_is_header(const grib_handle* h, const char* key, int* err);
int codes_bufr_key_is_coordinate(const grib_handle* h, const char* key, int* err);
/* string_util.cc*/
int strcmp_nocase(const char* s1, const char* s2);

View File

@ -1961,7 +1961,8 @@ static int adding_extra_key_attributes(grib_handle* h)
}
static grib_accessor* create_accessor_from_descriptor(const grib_accessor* a, grib_accessor* attribute, grib_section* section,
long ide, long subset, int add_dump_flag, int count, int add_extra_attributes)
long ide, long subset, int add_dump_flag, int add_coord_flag,
int count, int add_extra_attributes)
{
grib_accessor_bufr_data_array* self = (grib_accessor_bufr_data_array*)a;
char code[10] = {0,};
@ -1989,6 +1990,9 @@ static grib_accessor* create_accessor_from_descriptor(const grib_accessor* a, gr
creator.flags = GRIB_ACCESSOR_FLAG_DUMP;
operatorCreator.flags |= GRIB_ACCESSOR_FLAG_DUMP;
}
if (add_coord_flag) {
creator.flags |= GRIB_ACCESSOR_FLAG_BUFR_COORD; // ECC-1611
}
idx = self->compressedData ? self->elementsDescriptorsIndex->v[0]->v[ide] : self->elementsDescriptorsIndex->v[subset]->v[ide];
@ -1996,6 +2000,7 @@ static grib_accessor* create_accessor_from_descriptor(const grib_accessor* a, gr
case 0:
case 1:
creator.name = grib_context_strdup(a->context, self->expanded->v[idx]->shortName);
/* ECC-325: store alloc'd string (due to strdup) for clean up later */
grib_sarray_push(a->context, self->tempStrings, creator.name);
elementAccessor = grib_accessor_factory(section, &creator, 0, NULL);
@ -2466,7 +2471,7 @@ static int create_keys(const grib_accessor* a, long onlySubset, long startSubset
grib_accessor* elementFromBitmap = NULL;
grib_handle* hand = grib_handle_of_accessor(a);
/*int reuseBitmap=0;*/
int add_dump_flag = 1, count = 0;
int add_dump_flag = 1, add_coord_flag = 0, count = 0;
/*int forceGroupClosure=0;*/
creatorGroup.op = (char*)"bufr_group";
@ -2533,11 +2538,13 @@ static int create_keys(const grib_accessor* a, long onlySubset, long startSubset
continue; /* Descriptor does not have an associated key e.g. inside op 203YYY */
}
elementFromBitmap = NULL;
add_coord_flag = 0;
if (descriptor->F == 0 && IS_COORDINATE_DESCRIPTOR(descriptor->X) &&
self->unpackMode == CODES_BUFR_UNPACK_STRUCTURE) {
const int sidx = descriptor->Y + significanceQualifierIndexArray[descriptor->X] * NUMBER_OF_QUALIFIERS_PER_CATEGORY;
DebugAssert(sidx > 0);
groupNumber++;
add_coord_flag = 1;
if (significanceQualifierGroup[sidx]) {
groupSection = significanceQualifierGroup[sidx]->parent;
@ -2562,6 +2569,7 @@ static int create_keys(const grib_accessor* a, long onlySubset, long startSubset
gaGroup = grib_accessor_factory(groupSection, &creatorGroup, 0, NULL);
gaGroup->sub_section = grib_section_create(hand, gaGroup);
gaGroup->bufr_group_number = groupNumber;
accessor_constant_set_type(gaGroup, GRIB_TYPE_LONG);
accessor_constant_set_dval(gaGroup, groupNumber);
grib_push_accessor(gaGroup, groupSection->block);
@ -2675,7 +2683,8 @@ static int create_keys(const grib_accessor* a, long onlySubset, long startSubset
grib_accessors_list_push(self->dataAccessors, asn, rank);
}
count++;
elementAccessor = create_accessor_from_descriptor(a, associatedFieldAccessor, section, ide, iss, add_dump_flag, count, add_extra_attributes);
elementAccessor = create_accessor_from_descriptor(a, associatedFieldAccessor, section, ide, iss,
add_dump_flag, add_coord_flag, count, add_extra_attributes);
if (!elementAccessor) {
err = GRIB_DECODING_ERROR;
return err;

View File

@ -57,8 +57,6 @@ static void init(grib_accessor*, const long, grib_arguments*);
//static void init_class(grib_accessor_class*);
static int unpack_double_element(grib_accessor*, size_t i, double* val);
static int unpack_double_element_set(grib_accessor*, const size_t* index_array, size_t len, double* val_array);
static bool is_big_endian();
static void modify_aec_flags(long& flags);
typedef struct grib_accessor_data_ccsds_packing
{
@ -176,7 +174,24 @@ static int value_count(grib_accessor* a, long* count)
#error Version of libaec appears to be too old. Please upgrade.
#endif
const char* aec_get_error_message(int code)
static bool is_big_endian()
{
unsigned char is_big_endian = 0;
unsigned short endianess_test = 1;
return reinterpret_cast<const char*>(&endianess_test)[0] == is_big_endian;
}
static void modify_aec_flags(long* flags)
{
// ECC-1602: Performance improvement: enabled the use of native data types
*flags &= ~AEC_DATA_3BYTE; // disable support for 3-bytes per value
if (is_big_endian())
*flags |= AEC_DATA_MSB; // enable big-endian
else
*flags &= ~AEC_DATA_MSB; // enable little-endian
}
static const char* aec_get_error_message(int code)
{
if (code == AEC_MEM_ERROR) return "AEC_MEM_ERROR";
if (code == AEC_DATA_ERROR) return "AEC_DATA_ERROR";
@ -186,7 +201,7 @@ const char* aec_get_error_message(int code)
return "Unknown error code";
}
void print_aec_stream_info(struct aec_stream* strm, const char* func)
static void print_aec_stream_info(struct aec_stream* strm, const char* func)
{
fprintf(stderr, "ECCODES DEBUG CCSDS %s aec_stream.flags=%u\n", func, strm->flags);
fprintf(stderr, "ECCODES DEBUG CCSDS %s aec_stream.bits_per_sample=%u\n", func, strm->bits_per_sample);
@ -243,7 +258,7 @@ static int pack_double(grib_accessor* a, const double* val, size_t* len)
if ((err = grib_get_long_internal(hand, self->ccsds_rsi, &ccsds_rsi)) != GRIB_SUCCESS)
return err;
modify_aec_flags(ccsds_flags);
modify_aec_flags(&ccsds_flags);
// Special case
if (*len == 0) {
@ -482,23 +497,6 @@ cleanup:
return err;
}
static bool is_big_endian()
{
unsigned char is_big_endian = 0;
unsigned short endianess_test = 1;
return reinterpret_cast<const char*>(&endianess_test)[0] == is_big_endian;
}
static void modify_aec_flags(long& flags)
{
// ECC-1602: Performance improvement: enabled the use of native data types
flags &= ~AEC_DATA_3BYTE; // disable support for 3-bytes per value
if (is_big_endian())
flags |= AEC_DATA_MSB; // enable big-endian
else
flags &= ~AEC_DATA_MSB; // enable little-endian
}
template <typename T>
static int unpack(grib_accessor* a, T* val, size_t* len)
{
@ -553,7 +551,7 @@ static int unpack(grib_accessor* a, T* val, size_t* len)
if ((err = grib_get_long_internal(hand, self->ccsds_rsi, &ccsds_rsi)) != GRIB_SUCCESS)
return err;
modify_aec_flags(ccsds_flags);
modify_aec_flags(&ccsds_flags);
// TODO(masn): This should be called upstream
if (*len < n_vals)

View File

@ -562,23 +562,24 @@ struct grib_accessor
grib_accessor* parent_as_attribute;
};
#define GRIB_ACCESSOR_FLAG_READ_ONLY (1 << 1)
#define GRIB_ACCESSOR_FLAG_DUMP (1 << 2)
#define GRIB_ACCESSOR_FLAG_READ_ONLY (1 << 1)
#define GRIB_ACCESSOR_FLAG_DUMP (1 << 2)
#define GRIB_ACCESSOR_FLAG_EDITION_SPECIFIC (1 << 3)
#define GRIB_ACCESSOR_FLAG_CAN_BE_MISSING (1 << 4)
#define GRIB_ACCESSOR_FLAG_HIDDEN (1 << 5)
#define GRIB_ACCESSOR_FLAG_CONSTRAINT (1 << 6)
#define GRIB_ACCESSOR_FLAG_BUFR_DATA (1 << 7)
#define GRIB_ACCESSOR_FLAG_NO_COPY (1 << 8)
#define GRIB_ACCESSOR_FLAG_COPY_OK (1 << 9)
#define GRIB_ACCESSOR_FLAG_FUNCTION (1 << 10)
#define GRIB_ACCESSOR_FLAG_DATA (1 << 11)
#define GRIB_ACCESSOR_FLAG_NO_FAIL (1 << 12)
#define GRIB_ACCESSOR_FLAG_TRANSIENT (1 << 13)
#define GRIB_ACCESSOR_FLAG_STRING_TYPE (1 << 14)
#define GRIB_ACCESSOR_FLAG_LONG_TYPE (1 << 15)
#define GRIB_ACCESSOR_FLAG_DOUBLE_TYPE (1 << 16)
#define GRIB_ACCESSOR_FLAG_LOWERCASE (1 << 17)
#define GRIB_ACCESSOR_FLAG_CAN_BE_MISSING (1 << 4)
#define GRIB_ACCESSOR_FLAG_HIDDEN (1 << 5)
#define GRIB_ACCESSOR_FLAG_CONSTRAINT (1 << 6)
#define GRIB_ACCESSOR_FLAG_BUFR_DATA (1 << 7)
#define GRIB_ACCESSOR_FLAG_NO_COPY (1 << 8)
#define GRIB_ACCESSOR_FLAG_COPY_OK (1 << 9)
#define GRIB_ACCESSOR_FLAG_FUNCTION (1 << 10)
#define GRIB_ACCESSOR_FLAG_DATA (1 << 11)
#define GRIB_ACCESSOR_FLAG_NO_FAIL (1 << 12)
#define GRIB_ACCESSOR_FLAG_TRANSIENT (1 << 13)
#define GRIB_ACCESSOR_FLAG_STRING_TYPE (1 << 14)
#define GRIB_ACCESSOR_FLAG_LONG_TYPE (1 << 15)
#define GRIB_ACCESSOR_FLAG_DOUBLE_TYPE (1 << 16)
#define GRIB_ACCESSOR_FLAG_LOWERCASE (1 << 17)
#define GRIB_ACCESSOR_FLAG_BUFR_COORD (1 << 18)
/**
* a section accessor

View File

@ -41,6 +41,7 @@ list(APPEND test_c_bins
bufr_extract_headers
extract_offsets
bufr_check_descriptors
bufr_coordinate_descriptors
codes_new_from_samples
codes_set_samples_path
grib_sh_ieee64
@ -147,6 +148,7 @@ if( HAVE_BUILD_TOOLS )
bufr_templates
bufr_dump_data
bufr_dump_descriptors
bufr_coordinate_descriptors
bufr_dump_subset
bufr_dump_decode_filter
bufr_dump_encode_filter

View File

@ -0,0 +1,87 @@
/*
* (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 "eccodes.h"
#undef NDEBUG
#include <assert.h>
// Get the X part of a BUFR descriptor (FXY) and determine if it
// is a coordinate.
// See https://confluence.ecmwf.int/display/UDOC/What+are+coordinate+descriptors+-+ecCodes+BUFR+FAQ
static int is_coord_using_Xcode(const char* X)
{
if (strcmp(X, "01") == 0) return 1;
if (strcmp(X, "02") == 0) return 1;
if (strcmp(X, "04") == 0) return 1;
if (strcmp(X, "05") == 0) return 1;
if (strcmp(X, "06") == 0) return 1;
if (strcmp(X, "07") == 0) return 1;
if (strcmp(X, "08") == 0) return 1;
return 0;
}
int main(int argc, char* argv[])
{
int err = 0;
codes_handle* h = NULL;
char* filename = NULL;
FILE* fin = NULL;
int is_coord = 0;
assert (argc == 2);
filename = argv[1];
fin = fopen(filename, "rb");
assert(fin);
while ((h = codes_handle_new_from_file(NULL, fin, PRODUCT_BUFR, &err)) != NULL || err != CODES_SUCCESS) {
codes_bufr_keys_iterator* kiter = NULL;
CODES_CHECK(codes_set_long(h, "unpack", 1), 0);
kiter = codes_bufr_keys_iterator_new(h, 0);
assert(kiter);
while (codes_bufr_keys_iterator_next(kiter)) {
char* name = codes_bufr_keys_iterator_get_name(kiter);
if (strcmp(name, "subsetNumber") == 0) continue;
if (!codes_bufr_key_is_header(h, name, &err) && !err) {
char name1[256] = {0,};
char scode[256] = {0,};
char X[3] = {0,}; // the 'X' part of FXY
size_t slen = 256;
snprintf(name1, 256, "%s->code", name);
int error = codes_get_string(h, name1, scode, &slen);
if (!error) {
assert(strlen(scode) == 6);
X[0] = scode[1];
X[1] = scode[2];
X[2] = 0;
int is_X_coord = is_coord_using_Xcode(X);
is_coord = codes_bufr_key_is_coordinate(h, name, &error);
assert(!error);
if (is_coord != is_X_coord) {
fprintf(stderr, "ERROR: %s X=%s is_coord=%d is_X_coord=%d\n", name, X, is_coord, is_X_coord);
return 1;
}
}
}
else {
// header keys cannot be coordinate descriptors
is_coord = codes_bufr_key_is_coordinate(h, name, &err);
assert(!is_coord);
}
}
is_coord = codes_bufr_key_is_coordinate(h, "nosuchkey", &err);
assert(err == CODES_NOT_FOUND);
codes_bufr_keys_iterator_delete(kiter);
codes_handle_delete(h);
}
fclose(fin);
return 0;
}

View File

@ -0,0 +1,21 @@
#!/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="bufr_coordinate_descriptors_test"
temp=temp.$label.txt
bufr_files=`cat ${data_dir}/bufr/bufr_data_files.txt`
for f in ${bufr_files}; do
fpath=${data_dir}/bufr/$f
${test_dir}/bufr_coordinate_descriptors $fpath
done
rm -f $temp