From 2707c2fca26a39a763e890e38221d82ed1b1fdfb Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Mon, 27 Nov 2023 17:20:49 +0000 Subject: [PATCH] GRIB lightweight clone: WIP --- src/grib_handle.cc | 110 +++++++++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 34 deletions(-) diff --git a/src/grib_handle.cc b/src/grib_handle.cc index 07fac236e..876de92b2 100644 --- a/src/grib_handle.cc +++ b/src/grib_handle.cc @@ -326,49 +326,91 @@ grib_handle* grib_handle_clone(const grib_handle* h) return result; } +static bool can_create_clone_light(const grib_handle* h) +{ + // Only for GRIB, not BUFR etc + if (h->product_kind != PRODUCT_GRIB) return false; + + // Spectral data does not have constant fields! + long isGridded = 0; + int err = grib_get_long(h, "isGridded", &isGridded); + if (err || !isGridded) return false; + + return true; +} + grib_handle* grib_handle_clone_light(const grib_handle* h) { - int err = 0; - size_t size1 = 0; - const void* msg1 = NULL; - long edition = 0; + int err = 0; + long edition = 0; + grib_handle* result = NULL; - // Only for GRIB, not BUFR etc - if (h->product_kind != PRODUCT_GRIB) { - grib_context_log(h->context, GRIB_LOG_ERROR, "%s: Only supported for %s", - __func__, codes_get_product_name(PRODUCT_GRIB)); - return NULL; - } - - err = grib_get_long(h, "edition", &edition); - if (!err && edition == 1) { - grib_context_log(h->context, GRIB_LOG_ERROR, "%s: Edition not supported", __func__); - return NULL; - } - - err = grib_get_message_headers(h, &msg1, &size1); - if (err) return NULL; - - size1 += 4; - grib_handle* result = grib_handle_new_from_partial_message_copy(h->context, msg1, size1); - result->buffer->data[ size1 - 4 ] = '7'; - result->buffer->data[ size1 - 3 ] = '7'; - result->buffer->data[ size1 - 2 ] = '7'; - result->buffer->data[ size1 - 1 ] = '7'; - result->buffer->ulength = size1; - - result->product_kind = h->product_kind; - - long off = 64; // This is only true for GRIB edition 2 - err = grib_encode_unsigned_long( result->buffer->data, (unsigned long)size1, &off, 64); - if (err) { - printf("err=%s\n", grib_get_error_message(err)); + if (!can_create_clone_light(h)) { + // Lightweight clone not possible. Do a normal clone + return grib_handle_clone(h); + } + + char sample_name[1024]; /* name of the GRIB sample file */ + grib_get_long(h, "edition", &edition); + snprintf(sample_name, sizeof(sample_name), "GRIB%ld", edition); + grib_handle* h_sample = grib_handle_new_from_samples(NULL, sample_name); + + // Copy all sections except Bitmap and Data from h to h_sample + const int sections_to_copy = GRIB_SECTION_PRODUCT | GRIB_SECTION_LOCAL | GRIB_SECTION_GRID; + result = grib_util_sections_copy((grib_handle*)h, h_sample, sections_to_copy, &err); + if (!result || err) { + grib_context_log(h->context, GRIB_LOG_ERROR, "Failed to create lightweight clone"); + grib_handle_delete(h_sample); return NULL; } + grib_handle_delete(h_sample); return result; } +// grib_handle* grib_handle_clone_light(const grib_handle* h) +// { +// int err = 0; +// size_t size1 = 0; +// const void* msg1 = NULL; +// long edition = 0; + +// // Only for GRIB, not BUFR etc +// if (h->product_kind != PRODUCT_GRIB) { +// grib_context_log(h->context, GRIB_LOG_ERROR, "%s: Only supported for %s", +// __func__, codes_get_product_name(PRODUCT_GRIB)); +// return NULL; +// } + +// err = grib_get_long(h, "edition", &edition); +// if (!err && edition == 1) { +// grib_context_log(h->context, GRIB_LOG_ERROR, "%s: Edition not supported", __func__); +// return NULL; +// } + +// err = grib_get_message_headers(h, &msg1, &size1); +// if (err) return NULL; + +// size1 += 4; +// grib_handle* result = grib_handle_new_from_partial_message_copy(h->context, msg1, size1); +// result->buffer->data[ size1 - 4 ] = '7'; +// result->buffer->data[ size1 - 3 ] = '7'; +// result->buffer->data[ size1 - 2 ] = '7'; +// result->buffer->data[ size1 - 1 ] = '7'; +// result->buffer->ulength = size1; + +// result->product_kind = h->product_kind; + +// long off = 64; // This is only true for GRIB edition 2 +// err = grib_encode_unsigned_long( result->buffer->data, (unsigned long)size1, &off, 64); +// if (err) { +// printf("err=%s\n", grib_get_error_message(err)); +// return NULL; +// } + +// return result; +// } + grib_handle* codes_handle_new_from_file(grib_context* c, FILE* f, ProductKind product, int* error) { if (product == PRODUCT_GRIB)