diff --git a/src/eccodes_prototypes.h b/src/eccodes_prototypes.h index c9032e08e..26a6d0851 100644 --- a/src/eccodes_prototypes.h +++ b/src/eccodes_prototypes.h @@ -340,6 +340,7 @@ void grib_smart_table_delete(grib_context* c); /* grib_accessor_class_codetable.cc*/ void grib_codetable_delete(grib_context* c); +int codes_get_all_codetable_entries_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries); /* grib_accessor_class_codetable_units.cc*/ diff --git a/src/grib_accessor_class_codetable.cc b/src/grib_accessor_class_codetable.cc index e8e286623..6ecafa05a 100644 --- a/src/grib_accessor_class_codetable.cc +++ b/src/grib_accessor_class_codetable.cc @@ -523,6 +523,53 @@ void grib_codetable_delete(grib_context* c) } } +int codes_get_all_codetable_entries_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries) +{ + long lvalue = 0; + size_t size = 1; + int err = 0; + grib_context* c = h->context; + + grib_accessor* aa = grib_find_accessor(h, key); + if (!aa) return GRIB_NOT_FOUND; + + if (!STR_EQUAL(aa->cclass->name, "codetable")) { + return GRIB_INVALID_ARGUMENT; // key is not a codetable + } + + const grib_accessor_codetable* ca = (const grib_accessor_codetable*)aa; // could be dynamic_cast + + if ((err = grib_unpack_long(aa, &lvalue, &size)) != GRIB_SUCCESS) { + return err; + } + + const grib_codetable* table = ca->table; + if (!table) return GRIB_INTERNAL_ERROR; + + grib_codetable* cached_table = c->codetable; + while (cached_table) { + if (STR_EQUAL(table->recomposed_name[0], cached_table->recomposed_name[0])) { + // Found a cache entry that matches the recomposed name of ours + *entries = (code_table_entry*)calloc(cached_table->size, sizeof(code_table_entry)); + if (!*entries) { + return GRIB_OUT_OF_MEMORY; + } + size_t n = 0; + for (size_t i = 0; i < cached_table->size; i++) { + const char* abbrev = cached_table->entries[i].abbreviation; + if (abbrev) { + (*entries)[n++] = cached_table->entries[i]; + } + } + *num_entries = n; + return GRIB_SUCCESS; + } + cached_table = cached_table->next; + } + + return GRIB_CODE_NOT_FOUND_IN_TABLE; +} + static void dump(grib_accessor* a, grib_dumper* dumper) { grib_accessor_codetable* self = (grib_accessor_codetable*)a;