From 9cd5041d537f2190278af887eba53287e31e44fb Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 25 Aug 2023 06:10:07 +0000 Subject: [PATCH] ECC-1620: Prototype --- .../grib2/template.4.forecast_time.def | 8 +- src/CMakeLists.txt | 1 + src/grib_accessor_class.h | 1 + src/grib_accessor_class_g2end_step.cc | 454 ++++++++++-------- src/grib_accessor_class_g2step_range.cc | 240 +++++---- src/grib_accessor_class_step_in_units.cc | 183 ++++--- src/grib_accessor_classes_hash.cc | 160 +++--- src/grib_accessor_factory.h | 1 + src/grib_accessor_factory_hash_list | 1 + src/step.cc | 219 +++++++-- src/step.h | 336 +++++-------- src/step_utilities.cc | 31 +- src/step_utilities.h | 42 +- tests/grib_ecc-1620.sh | 167 +++++-- tests/grib_step.sh | 5 +- 15 files changed, 1080 insertions(+), 769 deletions(-) diff --git a/definitions/grib2/template.4.forecast_time.def b/definitions/grib2/template.4.forecast_time.def index 662310fc6..00df0b1a2 100644 --- a/definitions/grib2/template.4.forecast_time.def +++ b/definitions/grib2/template.4.forecast_time.def @@ -10,9 +10,11 @@ alias minutesAfterReferenceTimeOfDataCutoff=minutesAfterDataCutoff; # Indicator of unit of time range codetable[1] indicatorOfUnitOfTimeRange ('4.4.table',masterDir,localDir) : dump; -alias defaultStepUnits = one; # 1 means Hour. See code table 4.4 -template_nofail default_step_units "grib2/localConcepts/[centre:s]/default_step_units.def"; -codetable[1] stepUnits 'stepUnits.table' = defaultStepUnits : transient,dump,no_copy; +#alias defaultStepUnits = one; # 1 means Hour. See code table 4.4 +#alias forecastTimeUnit = indicatorOfUnitOfTimeRange; +#template_nofail default_step_units "grib2/localConcepts/[centre:s]/default_step_units.def"; +#codetable[1] stepUnits 'stepUnits.table' = defaultStepUnits : transient,dump,no_copy; +meta stepUnits optimal_step_units(forecastTime,indicatorOfUnitOfTimeRange,lengthOfTimeRange,indicatorOfUnitForTimeRange) : dump; # Forecast time in units defined by previous octet (GRIB-29: supports negative forecast time) signed[4] forecastTime : dump; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 69f39a820..8868d07fe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -167,6 +167,7 @@ list( APPEND eccodes_src_files grib_accessor_class_signed_bits.cc grib_accessor_class_section.cc grib_accessor_class_step_in_units.cc + grib_accessor_class_optimal_step_units.cc grib_accessor_class_section_length.cc grib_accessor_class_g1_message_length.cc grib_accessor_class_g1_section4_length.cc diff --git a/src/grib_accessor_class.h b/src/grib_accessor_class.h index 6aca52e29..ea6480a77 100644 --- a/src/grib_accessor_class.h +++ b/src/grib_accessor_class.h @@ -156,6 +156,7 @@ extern grib_accessor_class* grib_accessor_class_octahedral_gaussian; extern grib_accessor_class* grib_accessor_class_octet_number; extern grib_accessor_class* grib_accessor_class_offset_file; extern grib_accessor_class* grib_accessor_class_offset_values; +extern grib_accessor_class* grib_accessor_class_optimal_step_units; extern grib_accessor_class* grib_accessor_class_pack_bufr_values; extern grib_accessor_class* grib_accessor_class_pad; extern grib_accessor_class* grib_accessor_class_padding; diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index e43de49aa..304cc772f 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -20,6 +20,8 @@ CLASS = accessor SUPER = grib_accessor_class_long IMPLEMENTS = unpack_long;pack_long + IMPLEMENTS = unpack_double;pack_double + IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = init;dump MEMBERS = const char* start_step MEMBERS = const char* unit @@ -57,12 +59,12 @@ or edit "accessor.class" and rerun ./make_class.pl */ -static int pack_long(grib_accessor*, const long* val, size_t* len); -static int unpack_long(grib_accessor*, long* val, size_t* len); static int pack_double(grib_accessor*, const double* val, size_t* len); +static int pack_long(grib_accessor*, const long* val, size_t* len); +static int pack_string(grib_accessor*, const char*, size_t* len); static int unpack_double(grib_accessor*, double* val, size_t* len); -static int pack_string(grib_accessor*, const char* val, size_t* len); -static int unpack_string(grib_accessor*, char* val, size_t* len); +static int unpack_long(grib_accessor*, long* val, size_t* len); +static int unpack_string(grib_accessor*, char*, size_t* len); static void dump(grib_accessor*, grib_dumper*); static void init(grib_accessor*, const long, grib_arguments*); @@ -115,9 +117,9 @@ static grib_accessor_class _grib_accessor_class_g2end_step = { 0, /* is_missing */ &pack_long, /* pack_long */ &unpack_long, /* unpack_long */ - 0, //&pack_double, /* pack_double */ + &pack_double, /* pack_double */ 0, /* pack_float */ - 0, //&unpack_double, /* unpack_double */ + &unpack_double, /* unpack_double */ 0, /* unpack_float */ &pack_string, /* pack_string */ &unpack_string, /* unpack_string */ @@ -241,36 +243,27 @@ static int convert_time_range( Assert(lengthOfTimeRange != NULL); if (indicatorOfUnitForTimeRange != stepUnits) { - Step step{(int) *lengthOfTimeRange, indicatorOfUnitForTimeRange}; - if (stepUnits != 255) { - step.setUnit(stepUnits); + long u2sf_step_unit; + long coded_time_range_sec = (*lengthOfTimeRange) * u2s2[indicatorOfUnitForTimeRange]; + if (coded_time_range_sec < 0) { + long u2sf; + int factor = 60; + if (u2s2[indicatorOfUnitForTimeRange] % factor) + return GRIB_DECODING_ERROR; + if (u2s[stepUnits] % factor) + return GRIB_DECODING_ERROR; + u2sf = u2s2[indicatorOfUnitForTimeRange] / factor; + coded_time_range_sec = (*lengthOfTimeRange) * u2sf; + u2sf_step_unit = u2s[stepUnits] / factor; } else { - step.setUnit(indicatorOfUnitForTimeRange); + u2sf_step_unit = u2s[stepUnits]; } - *lengthOfTimeRange = step.value(); - - //long u2sf_step_unit; - //long coded_time_range_sec = (*lengthOfTimeRange) * u2s2[indicatorOfUnitForTimeRange]; - //if (coded_time_range_sec < 0) { - // long u2sf; - // int factor = 60; - // if (u2s2[indicatorOfUnitForTimeRange] % factor) - // return GRIB_DECODING_ERROR; - // if (u2s[stepUnits] % factor) - // return GRIB_DECODING_ERROR; - // u2sf = u2s2[indicatorOfUnitForTimeRange] / factor; - // coded_time_range_sec = (*lengthOfTimeRange) * u2sf; - // u2sf_step_unit = u2s[stepUnits] / factor; - //} - //else { - // u2sf_step_unit = u2s[stepUnits]; - //} - //if (coded_time_range_sec % u2sf_step_unit != 0) { - // grib_context_log(h->context, GRIB_LOG_ERROR, "unable to convert endStep in stepUnits"); - // return GRIB_WRONG_STEP_UNIT; - //} - //*lengthOfTimeRange = coded_time_range_sec / u2sf_step_unit; + if (coded_time_range_sec % u2sf_step_unit != 0) { + grib_context_log(h->context, GRIB_LOG_ERROR, "unable to convert endStep in stepUnits"); + return GRIB_WRONG_STEP_UNIT; + } + *lengthOfTimeRange = coded_time_range_sec / u2sf_step_unit; } return GRIB_SUCCESS; @@ -381,10 +374,20 @@ static int unpack_multiple_time_ranges(grib_accessor* a, long* val, size_t* len) static int unpack_long(grib_accessor* a, long* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; + grib_handle* h = grib_handle_of_accessor(a); + int ret = 0; + + //if (futureOutputEnabled(h)) { + // StepRange range; + // if ((ret = getOptTimeRange(h, range)) != GRIB_SUCCESS) + // return ret; + + // *val = range.endStep().value(); + //} + //else { int err = 0; long start_step; long numberOfTimeRange; - grib_handle* h = grib_handle_of_accessor(a); if ((err = grib_get_long_internal(h, self->start_step, &start_step))) return err; @@ -401,208 +404,275 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) Assert(numberOfTimeRange == 1 || numberOfTimeRange == 2); if (numberOfTimeRange == 1) { - return unpack_one_time_range(a, val, len); + ret = unpack_one_time_range(a, val, len); + return ret; } else { - return unpack_multiple_time_ranges(a, val, len); + ret = unpack_multiple_time_ranges(a, val, len); + return ret; } + //} + + return GRIB_SUCCESS; } // TODO(maee): Re-implement calendar-based stepRange using std::chrono static int pack_long(grib_accessor* a, const long* val, size_t* len) { - //grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; - grib_handle* h = grib_handle_of_accessor(a); - int ret = 0; + grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; + grib_handle* h = grib_handle_of_accessor(a); + int err = 0; - size_t stepOutputFormatSize = 128; - char stepOutputFormat[stepOutputFormatSize]; - if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) - return ret; + long year; + long month; + long day; + long hour; + long minute; + long second; - if (strcmp(stepOutputFormat, "future") == 0) { - Step step{*val, "h"}; - ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit().to_long()); - if (ret) - return ret; + long start_step; + long unit, coded_unit; + long year_of_end_of_interval; + long month_of_end_of_interval; + long day_of_end_of_interval; + long hour_of_end_of_interval; + long minute_of_end_of_interval = 0; + long second_of_end_of_interval = 0; - ret = grib_set_long_internal(h, "lengthOfTimeRange", step.value()); - if (ret) - return ret; - return GRIB_SUCCESS; + long coded_time_range, time_range, typeOfTimeIncrement; + + double dend, dstep; + + /*point in time */ + if (self->year == NULL) { + err = grib_set_long_internal(h, self->start_step, *val); + return err; } - else { - grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; - grib_handle* h = grib_handle_of_accessor(a); - int err = 0; + if ((err = grib_get_long_internal(h, self->coded_unit, &coded_unit))) + return err; + if ((err = grib_get_long_internal(h, self->unit, &unit))) + return err; + if ((err = grib_get_long_internal(h, self->year, &year))) + return err; + if ((err = grib_get_long_internal(h, self->month, &month))) + return err; + if ((err = grib_get_long_internal(h, self->day, &day))) + return err; + if ((err = grib_get_long_internal(h, self->hour, &hour))) + return err; + if ((err = grib_get_long_internal(h, self->minute, &minute))) + return err; + if ((err = grib_get_long_internal(h, self->second, &second))) + return err; - long year; - long month; - long day; - long hour; - long minute; - long second; + if ((err = grib_get_long_internal(h, self->start_step, &start_step))) + return err; + if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement))) + return err; - long start_step; - long unit, coded_unit; - long year_of_end_of_interval; - long month_of_end_of_interval; - long day_of_end_of_interval; - long hour_of_end_of_interval; - long minute_of_end_of_interval = 0; - long second_of_end_of_interval = 0; + time_range = *val - start_step; - long coded_time_range, time_range, typeOfTimeIncrement; - - double dend, dstep; - - /*point in time */ - if (self->year == NULL) { - err = grib_set_long_internal(h, self->start_step, *val); - return err; - } - - if ((err = grib_get_long_internal(h, self->coded_unit, &coded_unit))) - return err; - if ((err = grib_get_long_internal(h, self->unit, &unit))) - return err; - if ((err = grib_get_long_internal(h, self->year, &year))) - return err; - if ((err = grib_get_long_internal(h, self->month, &month))) - return err; - if ((err = grib_get_long_internal(h, self->day, &day))) - return err; - if ((err = grib_get_long_internal(h, self->hour, &hour))) - return err; - if ((err = grib_get_long_internal(h, self->minute, &minute))) - return err; - if ((err = grib_get_long_internal(h, self->second, &second))) - return err; - - if ((err = grib_get_long_internal(h, self->start_step, &start_step))) - return err; - if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement))) - return err; - - time_range = *val - start_step; - - if (time_range < 0) { - grib_context_log(h->context, GRIB_LOG_ERROR, - "endStep < startStep (%ld < %ld)", *val, start_step); - return GRIB_WRONG_STEP; - } - - err = grib_datetime_to_julian(year, month, day, hour, minute, second, &dend); - if (err != GRIB_SUCCESS) - return err; - - dstep = (((double)(*val)) * u2s[unit]) / u2s[2]; /* in days */ - dend += dstep; - - err = grib_julian_to_datetime(dend, &year_of_end_of_interval, &month_of_end_of_interval, - &day_of_end_of_interval, &hour_of_end_of_interval, - &minute_of_end_of_interval, &second_of_end_of_interval); - if (err != GRIB_SUCCESS) - return err; - - if ((err = grib_set_long_internal(h, self->year_of_end_of_interval, year_of_end_of_interval))) - return err; - if ((err = grib_set_long_internal(h, self->month_of_end_of_interval, month_of_end_of_interval))) - return err; - if ((err = grib_set_long_internal(h, self->day_of_end_of_interval, day_of_end_of_interval))) - return err; - if ((err = grib_set_long_internal(h, self->hour_of_end_of_interval, hour_of_end_of_interval))) - return err; - if ((err = grib_set_long_internal(h, self->minute_of_end_of_interval, minute_of_end_of_interval))) - return err; - if ((err = grib_set_long_internal(h, self->second_of_end_of_interval, second_of_end_of_interval))) - return err; - - if (time_range * u2s[unit] % u2s2[coded_unit]) { - coded_unit = unit; - if ((err = grib_set_long_internal(h, self->coded_unit, coded_unit))) - return err; - coded_time_range = time_range; - } - else - coded_time_range = (time_range * u2s[unit]) / u2s2[coded_unit]; - - if (typeOfTimeIncrement != 1) { - /* 1 means "Successive times processed have same forecast time, start time of forecast is incremented" */ - /* Note: For this case, length of timeRange is not related to step and so should NOT be used to calculate step */ - if ((err = grib_set_long_internal(h, self->coded_time_range, coded_time_range))) - return err; - } - - return GRIB_SUCCESS; + if (time_range < 0) { + grib_context_log(h->context, GRIB_LOG_ERROR, + "endStep < startStep (%ld < %ld)", *val, start_step); + return GRIB_WRONG_STEP; } -} -static int pack_string(grib_accessor* a, const char* val, size_t* len) { - //grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; - grib_handle* h = grib_handle_of_accessor(a); - int ret = 0; + err = grib_datetime_to_julian(year, month, day, hour, minute, second, &dend); + if (err != GRIB_SUCCESS) + return err; - Step step = Step(parse_step(std::string(val))); + dstep = (((double)(*val)) * u2s[unit]) / u2s[2]; /* in days */ + dend += dstep; - ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit().to_long()); - if (ret) - return ret; + err = grib_julian_to_datetime(dend, &year_of_end_of_interval, &month_of_end_of_interval, + &day_of_end_of_interval, &hour_of_end_of_interval, + &minute_of_end_of_interval, &second_of_end_of_interval); + if (err != GRIB_SUCCESS) + return err; - ret = grib_set_long_internal(h, "lengthOfTimeRange", step.value()); - if (ret) - return ret; + if ((err = grib_set_long_internal(h, self->year_of_end_of_interval, year_of_end_of_interval))) + return err; + if ((err = grib_set_long_internal(h, self->month_of_end_of_interval, month_of_end_of_interval))) + return err; + if ((err = grib_set_long_internal(h, self->day_of_end_of_interval, day_of_end_of_interval))) + return err; + if ((err = grib_set_long_internal(h, self->hour_of_end_of_interval, hour_of_end_of_interval))) + return err; + if ((err = grib_set_long_internal(h, self->minute_of_end_of_interval, minute_of_end_of_interval))) + return err; + if ((err = grib_set_long_internal(h, self->second_of_end_of_interval, second_of_end_of_interval))) + return err; + + if (time_range * u2s[unit] % u2s2[coded_unit]) { + coded_unit = unit; + if ((err = grib_set_long_internal(h, self->coded_unit, coded_unit))) + return err; + coded_time_range = time_range; + } + else + coded_time_range = (time_range * u2s[unit]) / u2s2[coded_unit]; + + if (typeOfTimeIncrement != 1) { + /* 1 means "Successive times processed have same forecast time, start time of forecast is incremented" */ + /* Note: For this case, length of timeRange is not related to step and so should NOT be used to calculate step */ + if ((err = grib_set_long_internal(h, self->coded_time_range, coded_time_range))) + return err; + } return GRIB_SUCCESS; } -static int unpack_string(grib_accessor* a, char* val, size_t* len) { +static int unpack_string(grib_accessor* a, char* val, size_t* len) +{ grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - auto [start, stop] = getTimeRange(h); - auto [step_a, step_b] = findCommonUnits(start.optimizeUnit(), stop.optimizeUnit()); - step_a.hide_hour_unit(); - step_b.hide_hour_unit(); + long step_units_old; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_old)) != GRIB_SUCCESS) + return ret; + if ((ret = grib_set_long_internal(h, "stepUnits", UnitType{Unit::SECOND}.toLong())) != GRIB_SUCCESS) + return ret; + + long step_value; + size_t step_len = 0; + if ((ret = unpack_long(a, &step_value, &step_len)) != GRIB_SUCCESS) + return ret; + + + Step step(step_value, Unit::SECOND); + step.setUnit(step_units_old); + + if ((ret = grib_set_long_internal(h, "stepUnits", step_units_old)) != GRIB_SUCCESS) + return ret; + + step.hideHourUnit(); if (futureOutputEnabled(h)) { - snprintf(val, *len, "%ld%s", step_b.value(), step_b.unit().to_string().c_str()); + snprintf(val, *len, "%s", step.toString().c_str()); } else { - snprintf(val, *len, "%ld", step_b.value()); + snprintf(val, *len, "%ld", step.value()); } + + return GRIB_SUCCESS; + + + //grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; + //grib_handle* h = grib_handle_of_accessor(a); + //int ret = 0; + + //long start_step_long; + //size_t start_step_len = 0; + //if ((ret = unpack_long(a, &start_step_long, &start_step_len)) != GRIB_SUCCESS) + // return ret; + + //long step_units; + //if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + // return ret; + + //Step start_step(start_step_long, step_units); + //start_step.hideHourUnit(); + //if (futureOutputEnabled(h)) { + // snprintf(val, *len, "%s", start_step.toString().c_str()); + //} + //else { + // snprintf(val, *len, "%ld", start_step.value()); + //} + + //return GRIB_SUCCESS; +} + + +static int pack_double(grib_accessor* a, const double* val, size_t* len) +{ + grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; + grib_handle* h = grib_handle_of_accessor(a); + int ret = 0; + + long step_units; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + return ret; + Step end_step{*val, step_units}; + + end_step.optimizeUnit(); + if ((ret = grib_set_long_internal(h, "stepUnits", end_step.unit().toLong())) != GRIB_SUCCESS) + return ret; + long end_step_value = end_step.value(); + + if ((ret = pack_long(a, &end_step_value, len)) != GRIB_SUCCESS) + return ret; + return GRIB_SUCCESS; } -static int pack_double(grib_accessor* a, const double* val, size_t* len) { - // not implemented - return GRIB_NOT_IMPLEMENTED; + +static int pack_string(grib_accessor* a, const char* val, size_t* len) +{ + //grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; + grib_handle* h = grib_handle_of_accessor(a); + int ret = 0; + Step end_step = step_from_string(val); + end_step.optimizeUnit(); + if ((ret = grib_set_long_internal(h, "stepUnits", end_step.unit().toLong())) != GRIB_SUCCESS) + return ret; + + double end_step_value = end_step.value(); + size_t end_step_len = 0; + + if ((ret = pack_double(a, &end_step_value, &end_step_len)) != GRIB_SUCCESS) + return ret; + return GRIB_SUCCESS; + + ////grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; + //grib_handle* h = grib_handle_of_accessor(a); + //int ret = 0; + + //if (futureOutputEnabled(h)) { + // // TODO(EB): Export code to a function + // long stepUnitsLong; + // if ((ret = grib_get_long_internal(h, "stepUnits", &stepUnitsLong)) != GRIB_SUCCESS) + // return ret; + // UnitType stepUnits{stepUnitsLong}; + + // StepRange range; + // getOptTimeRange(h, range); + // UnitType endStepUnit = range.endStep().unit(); + // Step endStep{parseStep(val)}; + // Step length = endStep - range.startStep(); + // if (stepUnits != Unit::MISSING) { + // length.setUnit(stepUnits); + // } + + // length.optimizeUnit(); + // if ((ret = grib_set_double_internal(h, "lengthOfTimeRange", length.value()) != GRIB_SUCCESS)) + // return ret; + // if ((ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", length.unit().toLong())) != GRIB_SUCCESS) + // return ret; + // return GRIB_SUCCESS; + //} + //else { + // return GRIB_NOT_IMPLEMENTED; + //} } -static int unpack_double(grib_accessor* a, double* val, size_t* len) { + +static int unpack_double(grib_accessor* a, double* val, size_t* len) +{ //grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - long unit; - ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit); - if (ret) + long a_val; + if ((ret = unpack_long(a, &a_val, len)) != GRIB_SUCCESS) + return ret; + long step_units; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; - long value; - ret = grib_get_long_internal(h, "lengthOfTimeRange", &value); - if (ret) - return ret; - - long stepUnits; - ret = grib_get_long_internal(h, "stepUnits", &stepUnits); - if (ret) - return ret; - - Step step = Step(value, unit); - *val = step.setUnit(stepUnits).value(); - + Step end_step{a_val, step_units}; + *val = end_step.value(); return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index a3ff5a0bb..b103f02f6 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -14,6 +14,7 @@ #include "grib_api_internal.h" #include "step.h" +#include "step_range.h" #include "step_utilities.h" #include /* @@ -23,7 +24,9 @@ CLASS = accessor SUPER = grib_accessor_class_gen IMPLEMENTS = pack_string;unpack_string;value_count - IMPLEMENTS = pack_long;unpack_long;dump + IMPLEMENTS = unpack_long;pack_long + IMPLEMENTS = unpack_double;pack_double + IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = get_native_type;string_length IMPLEMENTS = init MEMBERS = const char* startStep @@ -43,13 +46,14 @@ or edit "accessor.class" and rerun ./make_class.pl */ static int get_native_type(grib_accessor*); +static int pack_double(grib_accessor*, const double* val, size_t* len); static int pack_long(grib_accessor*, const long* val, size_t* len); static int pack_string(grib_accessor*, const char*, size_t* len); +static int unpack_double(grib_accessor*, double* val, size_t* len); static int unpack_long(grib_accessor*, long* val, size_t* len); static int unpack_string(grib_accessor*, char*, size_t* len); static size_t string_length(grib_accessor*); static int value_count(grib_accessor*, long*); -static void dump(grib_accessor*, grib_dumper*); static void init(grib_accessor*, const long, grib_arguments*); typedef struct grib_accessor_g2step_range @@ -72,7 +76,7 @@ static grib_accessor_class _grib_accessor_class_g2step_range = { &init, /* init */ 0, /* post_init */ 0, /* destroy */ - &dump, /* dump */ + 0, /* dump */ 0, /* next_offset */ &string_length, /* get length of string */ &value_count, /* get number of values */ @@ -84,9 +88,9 @@ static grib_accessor_class _grib_accessor_class_g2step_range = { 0, /* is_missing */ &pack_long, /* pack_long */ &unpack_long, /* unpack_long */ - 0, /* pack_double */ + &pack_double, /* pack_double */ 0, /* pack_float */ - 0, /* unpack_double */ + &unpack_double, /* unpack_double */ 0, /* unpack_float */ &pack_string, /* pack_string */ &unpack_string, /* unpack_string */ @@ -140,43 +144,49 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) char buf[100]; int ret = 0; size_t size = 0; + long start_value = 0; + long end_value = 0; + long step_units_value = 0; - if (futureOutputEnabled(h)) { - Step step_a; - Step step_b; - if ((ret = getOptTimeRange(h, step_a, step_b)) != GRIB_SUCCESS) - return ret; + if ((ret = grib_get_long_internal(h, self->startStep, &start_value)) != GRIB_SUCCESS) + return ret; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_value)) != GRIB_SUCCESS) + return ret; - if (step_a == step_b) { - //snprintf(buf, sizeof(buf), "%ld%s", step_a.value(), step_a.unit().to_string().c_str()); - snprintf(buf, sizeof(buf), "%0.2f%s", step_a.value(), step_a.unit().to_string().c_str()); + + Step start_step = Step(start_value, step_units_value); + start_step.hideHourUnit(); + if (self->endStep == NULL) { + if (futureOutputEnabled(h)) { + snprintf(buf, sizeof(buf), "%s", start_step.toString().c_str()); } else { - //snprintf(buf, sizeof(buf), "%ld%s-%ld%s", step_a.value(), step_a.unit().to_string().c_str(), step_b.value(), step_b.unit().to_string().c_str()); - snprintf(buf, sizeof(buf), "%0.2f%s-%0.2f%s", step_a.value(), step_a.unit().to_string().c_str(), step_b.value(), step_b.unit().to_string().c_str()); + snprintf(buf, sizeof(buf), "%ld", start_value); } } else { - long start = 0, theEnd = 0; - - ret = grib_get_long_internal(h, self->startStep, &start); - if (ret) + if ((ret = grib_get_long_internal(h, self->endStep, &end_value)) != GRIB_SUCCESS) return ret; - if (self->endStep == NULL) { - snprintf(buf, sizeof(buf), "%ld", start); - } - else { - if ((ret = grib_get_long_internal(h, self->endStep, &theEnd)) != GRIB_SUCCESS) - return ret; - - if (start == theEnd) { - snprintf(buf, sizeof(buf), "%ld", theEnd); + if (futureOutputEnabled(h)) { + Step end_step = Step(end_value, step_units_value); + end_step.hideHourUnit(); + if (start_value == end_value) { + snprintf(buf, sizeof(buf), "%s", end_step.toString().c_str()); } else { - snprintf(buf, sizeof(buf), "%ld-%ld", start, theEnd); + snprintf(buf, sizeof(buf), "%s-%s", start_step.toString().c_str(), end_step.toString().c_str()); } } + else { + if (start_value == end_value) { + snprintf(buf, sizeof(buf), "%ld", end_value); + } + else { + snprintf(buf, sizeof(buf), "%ld-%ld", start_value, end_value); + } + } + } size = strlen(buf) + 1; @@ -198,62 +208,26 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - size_t stepOutputFormatSize = 128; - char stepOutputFormat[stepOutputFormatSize]; - if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) + std::vector steps = parseRange(val); + if (steps.size() == 0) + return GRIB_INVALID_ARGUMENT; + + Step step_0 = steps[0]; + Step step_1; + if (steps.size() > 1) { + std::tie(step_0, step_1) = findCommonUnits(steps[0].optimizeUnit(), steps[1].optimizeUnit()); + if ((ret = grib_set_long_internal(h, "stepUnits", step_0.unit().toLong()))) + return ret; + } + + if ((ret = grib_set_long_internal(h, self->startStep, step_0.value()))) return ret; - if (strcmp(stepOutputFormat, "future") == 0) { - std::vector> steps = parse_range(val); - if (steps.size() == 0) { - return GRIB_INVALID_ARGUMENT; - } - if (steps.size() == 1) { - steps[0].optimizeUnit(); - if ((ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", steps[0].unit().to_long()))) - return ret; - if ((ret = grib_set_long_internal(h, "forecastTime", steps[0].value()))) - return ret; - } - else if (steps.size() == 2) { - steps[0].optimizeUnit(); - steps[1].optimizeUnit(); - auto [s0, s1] = findCommonUnits(steps[0], steps[1]); - - if ((ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", s0.unit().to_long()))) - return ret; - if ((ret = grib_set_long_internal(h, "forecastTime", s0.value()))) - return ret; - - if ((ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", s1.unit().to_long()))) - return ret; - if ((ret = grib_set_long_internal(h, "lengthOfTimeRange", s1.value()))) - return ret; - } - else { - std::string msg = std::string("Invalid range: ") + val; - throw std::runtime_error(msg); - } - } - else { - long start = 0, theEnd = -1; - char *p = NULL, *q = NULL; - - start = strtol(val, &p, 10); - theEnd = start; - - if (*p != 0) - theEnd = strtol(++p, &q, 10); - if ((ret = grib_set_long_internal(h, self->startStep, start))) + if ((self->endStep != NULL) && (steps.size() > 1)) { + if ((ret = grib_set_long_internal(h, self->endStep, step_1.value()))) return ret; - - if (self->endStep != NULL) { - if ((ret = grib_set_long_internal(h, self->endStep, theEnd))) - return ret; - } } - - return 0; + return GRIB_SUCCESS; } static int value_count(grib_accessor* a, long* count) @@ -276,40 +250,96 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return pack_string(a, buff, &bufflen); } +static int pack_double(grib_accessor* a, const double* val, size_t* len) +{ + // TODO(EB) + return GRIB_NOT_IMPLEMENTED; +} + +static int unpack_double(grib_accessor* a, double* val, size_t* len) +{ + grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; + grib_handle* h = grib_handle_of_accessor(a); + char buf[100]; + int ret = 0; + size_t size = 0; + long start_value = 0; + long end_value = 0; + long step_units_value = 0; + + if ((ret = grib_get_long_internal(h, self->startStep, &start_value)) != GRIB_SUCCESS) + return ret; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_value)) != GRIB_SUCCESS) + return ret; + + Step start_step = Step(start_value, step_units_value); + start_step.hideHourUnit(); + if (self->endStep == NULL) { + *val = start_step.value(); + } + else { + if ((ret = grib_get_long_internal(h, self->endStep, &end_value)) != GRIB_SUCCESS) + return ret; + Step end_step = Step(end_value, step_units_value); + *val = end_step.value(); + } + + return GRIB_SUCCESS; + + ////grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; + //grib_handle* h = grib_handle_of_accessor(a); + //int ret = 0; + + //StepRange range; + //if ((ret = getOptTimeRange(h, range)) != GRIB_SUCCESS) + // return ret; + + //*val = range.endStep().value(); + + //return 0; +} + static int unpack_long(grib_accessor* a, long* val, size_t* len) { grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; grib_handle* h = grib_handle_of_accessor(a); - int ret = 0; + char buf[100]; + int ret = 0; + size_t size = 0; + long start_value = 0; + long end_value = 0; + long step_units_value = 0; - size_t stepOutputFormatSize = 128; - char stepOutputFormat[stepOutputFormatSize]; - if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) + if ((ret = grib_get_long_internal(h, self->startStep, &start_value)) != GRIB_SUCCESS) + return ret; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_value)) != GRIB_SUCCESS) return ret; - //if (strcmp(stepOutputFormat, "future") == 0) { - auto [forcastTime, lengthOfTimeRange] = getTimeRange(h); - auto [optForecastTime, optLenghtOfTimeRange] = findCommonUnits(forcastTime.optimizeUnit(), lengthOfTimeRange.optimizeUnit()); - *val = optLenghtOfTimeRange.value(); - //} - //else { - // char buff[100]; - // size_t bufflen = 100; - // long start, theEnd; - // char* p = buff; - // char* q = NULL; - // if ((ret = unpack_string(a, buff, &bufflen)) != GRIB_SUCCESS) - // return ret; + Step start_step = Step(start_value, step_units_value); + start_step.hideHourUnit(); + if (self->endStep == NULL) { + *val = start_step.value(); + } + else { + if ((ret = grib_get_long_internal(h, self->endStep, &end_value)) != GRIB_SUCCESS) + return ret; + Step end_step = Step(end_value, step_units_value); + *val = end_step.value(); + } - // start = strtol(buff, &p, 10); - // theEnd = start; - // if (*p != 0) - // theEnd = strtol(++p, &q, 10); + return GRIB_SUCCESS; - // *val = theEnd; - //} + ////grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; + //grib_handle* h = grib_handle_of_accessor(a); + //int ret = 0; - return 0; + //StepRange range; + //if ((ret = getOptTimeRange(h, range)) != GRIB_SUCCESS) + // return ret; + + //*val = range.endStep().value(); + + //return 0; } static int get_native_type(grib_accessor* a) diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index b8b27d0bb..e26e5a3ed 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -19,6 +19,8 @@ CLASS = accessor SUPER = grib_accessor_class_long IMPLEMENTS = unpack_long;pack_long + IMPLEMENTS = unpack_double;pack_double + IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = init;dump MEMBERS = const char* codedStep MEMBERS = const char* codedUnits @@ -40,12 +42,12 @@ or edit "accessor.class" and rerun ./make_class.pl */ -static int pack_long(grib_accessor*, const long* val, size_t* len); -static int unpack_long(grib_accessor*, long* val, size_t* len); static int pack_double(grib_accessor*, const double* val, size_t* len); +static int pack_long(grib_accessor*, const long* val, size_t* len); +static int pack_string(grib_accessor*, const char*, size_t* len); static int unpack_double(grib_accessor*, double* val, size_t* len); -static int pack_string(grib_accessor*, const char* val, size_t* len); -static int unpack_string(grib_accessor*, char* val, size_t* len); +static int unpack_long(grib_accessor*, long* val, size_t* len); +static int unpack_string(grib_accessor*, char*, size_t* len); static void dump(grib_accessor*, grib_dumper*); static void init(grib_accessor*, const long, grib_arguments*); @@ -85,9 +87,9 @@ static grib_accessor_class _grib_accessor_class_step_in_units = { 0, /* is_missing */ &pack_long, /* pack_long */ &unpack_long, /* unpack_long */ - 0, //&pack_double, /* pack_double */ + &pack_double, /* pack_double */ 0, /* pack_float */ - 0, //&unpack_double, /* unpack_double */ + &unpack_double, /* unpack_double */ 0, /* unpack_float */ &pack_string, /* pack_string */ &unpack_string, /* unpack_string */ @@ -175,19 +177,20 @@ static const int u2s[] = { static int unpack_long(grib_accessor* a, long* val, size_t* len) { grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; - int err = 0; - long codedStep, codedUnits, stepUnits; grib_handle* h = grib_handle_of_accessor(a); + int ret; + + long codedStep, codedUnits, stepUnits; int factor = 0; long u2sf, u2sf_step_unit; - if ((err = grib_get_long_internal(h, self->codedUnits, &codedUnits))) - return err; - if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits))) - return err; - if ((err = grib_get_long_internal(h, self->codedStep, &codedStep))) - return err; + if ((ret = grib_get_long_internal(h, self->codedUnits, &codedUnits))) + return ret; + if ((ret = grib_get_long_internal(h, self->stepUnits, &stepUnits))) + return ret; + if ((ret = grib_get_long_internal(h, self->codedStep, &codedStep))) + return ret; if (stepUnits != codedUnits) { *val = codedStep * u2s2[codedUnits]; @@ -206,9 +209,9 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) } if (*val % u2sf_step_unit != 0) { - err = grib_set_long_internal(h, self->stepUnits, codedUnits); + ret = grib_set_long_internal(h, self->stepUnits, codedUnits); *val = codedStep; - return err; + return ret; } *val = *val / u2sf_step_unit; } @@ -220,22 +223,9 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) static int pack_long(grib_accessor* a, const long* val, size_t* len) { - //grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; - //grib_handle* h = grib_handle_of_accessor(a); - //int ret = 0; - - //Step step{*val, "h"}; - //ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", step.unit().to_long()); - //if (ret) - // return ret; - - //ret = grib_set_long_internal(h, "forecastTime", step.value()); - //if (ret) - // return ret; - //return GRIB_SUCCESS; - grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); + int err = 0; long codedStep, codedUnits, stepUnits; long oldStep = 0; @@ -285,73 +275,140 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return grib_set_long_internal(grib_handle_of_accessor(a), self->codedStep, codedStep); } -static int pack_string(grib_accessor* a, const char* val, size_t* len) { +static int pack_string(grib_accessor* a, const char* val, size_t* len) +{ grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - Step step = Step(parse_step(std::string(val))); - ret = grib_set_long_internal(h, self->codedUnits, step.unit().to_long()); - if (ret) + Step step = step_from_string(val); + step.optimizeUnit(); + + if ((ret = grib_set_long_internal(h, self->stepUnits, step.unit().toLong()))) + return ret; + long step_value = step.value(); + if ((ret = pack_long(a, &step_value, len)) != GRIB_SUCCESS) return ret; - ret = grib_set_long_internal(h, self->codedStep, step.value()); - if (ret) - return ret; + //if ((ret = grib_set_long_internal(h, self->codedUnits, step.unit().toLong()))) + // return ret; + + //long step_value = step.value(); + //size_t step_value_len = 0; + //if ((ret = pack_long(a, &step_value, &step_value_len)) != GRIB_SUCCESS) + // return ret; return GRIB_SUCCESS; } -static int unpack_string(grib_accessor* a, char* val, size_t* len) { +static int unpack_string(grib_accessor* a, char* val, size_t* len) +{ grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - //auto [step, step_b] = getOptTimeRange(h); - Step step_a; - Step step_b; - if ((ret = getOptTimeRange(h, step_a, step_b)) != GRIB_SUCCESS) + + long step_units_old; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_old)) != GRIB_SUCCESS) return ret; - snprintf(val, *len, "%f%s", step_a.value(), step_a.unit().to_string().c_str()); + if ((ret = grib_set_long_internal(h, "stepUnits", UnitType{Unit::SECOND}.toLong())) != GRIB_SUCCESS) + return ret; + long step_value; + size_t step_len = 0; + if ((ret = unpack_long(a, &step_value, &step_len)) != GRIB_SUCCESS) + return ret; + + + Step step(step_value, Unit::SECOND); + step.setUnit(step_units_old); + + if ((ret = grib_set_long_internal(h, "stepUnits", step_units_old)) != GRIB_SUCCESS) + return ret; + + step.hideHourUnit(); if (futureOutputEnabled(h)) { - snprintf(val, *len, "%f%s", step_a.value(), step_a.unit().to_string().c_str()); + snprintf(val, *len, "%s", step.toString().c_str()); } else { - snprintf(val, *len, "%f", step_a.value()); + snprintf(val, *len, "%ld", step.value()); } return GRIB_SUCCESS; + ////grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; + //grib_handle* h = grib_handle_of_accessor(a); + //int ret = 0; + //StepRange range; + //if ((ret = getOptTimeRange(h, range)) != GRIB_SUCCESS) + // return ret; + + //if (futureOutputEnabled(h)) { + // snprintf(val, *len, "%s", range.startStepToString().c_str()); + //} + //else { + // snprintf(val, *len, "%ld", range.startStep().value()); + //} + + //return GRIB_SUCCESS; } -static int pack_double(grib_accessor* a, const double* val, size_t* len) { - return GRIB_NOT_IMPLEMENTED; -} - - -static int unpack_double(grib_accessor* a, double* val, size_t* len) { +static int pack_double(grib_accessor* a, const double* val, size_t* len) +{ grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - long unit; - ret = grib_get_long_internal(h, self->codedUnits, &unit); - if (ret) + long step_units; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; + Step start_step{*val, step_units}; - long value; - ret = grib_get_long_internal(h, self->codedStep, &value); - if (ret) + start_step.optimizeUnit(); + if ((ret = grib_set_long_internal(h, "stepUnits", start_step.unit().toLong())) != GRIB_SUCCESS) return ret; + long start_step_value = start_step.value(); - long stepUnits; - ret = grib_get_long_internal(h, self->stepUnits, &stepUnits); - if (ret) + if ((ret = pack_long(a, &start_step_value, len)) != GRIB_SUCCESS) return ret; - Step step{(double) value, unit}; - *val = step.setUnit(stepUnits).value(); - return GRIB_SUCCESS; } + + +static int unpack_double(grib_accessor* a, double* val, size_t* len) +{ + grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; + grib_handle* h = grib_handle_of_accessor(a); + int ret; + + long step_units_old; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_old)) != GRIB_SUCCESS) + return ret; + UnitType step_units{step_units_old}; + + if ((ret = grib_set_long_internal(h, "stepUnits", UnitType{Unit::SECOND}.toLong())) != GRIB_SUCCESS) + return ret; + + long value_secs; + size_t value_secs_len = 0; + if ((ret = unpack_long(a, &value_secs, &value_secs_len)) != GRIB_SUCCESS) + return ret; + + Step step(value_secs, Unit::SECOND); + step.setUnit(step_units_old); + *val = step.value(); + return GRIB_SUCCESS; + + //grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; + //grib_handle* h = grib_handle_of_accessor(a); + //int ret; + + //StepRange range; + //if ((ret = getOptTimeRange(h, range)) != GRIB_SUCCESS) + // return ret; + + //*val = range.startStep().value(); + //return GRIB_SUCCESS; + return GRIB_NOT_IMPLEMENTED; +} diff --git a/src/grib_accessor_classes_hash.cc b/src/grib_accessor_classes_hash.cc index a27a7a7a0..8f0f5075f 100644 --- a/src/grib_accessor_classes_hash.cc +++ b/src/grib_accessor_classes_hash.cc @@ -37,7 +37,7 @@ #line 6 "accessor_class_list.gperf" struct accessor_class_hash { char *name; grib_accessor_class **cclass;}; -#define TOTAL_KEYWORDS 218 +#define TOTAL_KEYWORDS 219 #define MIN_WORD_LENGTH 1 #define MAX_WORD_LENGTH 44 #define MIN_HASH_VALUE 1 @@ -51,7 +51,8 @@ struct accessor_class_hash { char *name; grib_accessor_class **cclass;}; #endif #endif -static unsigned int grib_accessor_classes_get_id (const char *str, size_t len) +static unsigned int +grib_accessor_classes_get_id (register const char *str, register size_t len) { static const unsigned short asso_values[] = { @@ -82,7 +83,7 @@ static unsigned int grib_accessor_classes_get_id (const char *str, size_t len) 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680 }; - unsigned int hval = len; + register unsigned int hval = len; switch (hval) { @@ -134,20 +135,20 @@ static const struct accessor_class_hash classes[] = {"int64", &grib_accessor_class_int64}, #line 72 "accessor_class_list.gperf" {"data_secondary_bitmap", &grib_accessor_class_data_secondary_bitmap}, -#line 202 "accessor_class_list.gperf" +#line 203 "accessor_class_list.gperf" {"time", &grib_accessor_class_time}, #line 69 "accessor_class_list.gperf" {"data_png_packing", &grib_accessor_class_data_png_packing}, {""}, -#line 190 "accessor_class_list.gperf" +#line 191 "accessor_class_list.gperf" {"size", &grib_accessor_class_size}, -#line 180 "accessor_class_list.gperf" - {"second_order_bits_per_value", &grib_accessor_class_second_order_bits_per_value}, -#line 187 "accessor_class_list.gperf" - {"signed", &grib_accessor_class_signed}, #line 181 "accessor_class_list.gperf" + {"second_order_bits_per_value", &grib_accessor_class_second_order_bits_per_value}, +#line 188 "accessor_class_list.gperf" + {"signed", &grib_accessor_class_signed}, +#line 182 "accessor_class_list.gperf" {"section", &grib_accessor_class_section}, -#line 203 "accessor_class_list.gperf" +#line 204 "accessor_class_list.gperf" {"times", &grib_accessor_class_times}, #line 70 "accessor_class_list.gperf" {"data_raw_packing", &grib_accessor_class_data_raw_packing}, @@ -157,19 +158,19 @@ static const struct accessor_class_hash classes[] = #line 13 "accessor_class_list.gperf" {"ascii", &grib_accessor_class_ascii}, {""}, -#line 182 "accessor_class_list.gperf" - {"section_length", &grib_accessor_class_section_length}, #line 183 "accessor_class_list.gperf" + {"section_length", &grib_accessor_class_section_length}, +#line 184 "accessor_class_list.gperf" {"section_padding", &grib_accessor_class_section_padding}, -#line 196 "accessor_class_list.gperf" +#line 197 "accessor_class_list.gperf" {"statistics", &grib_accessor_class_statistics}, -#line 199 "accessor_class_list.gperf" +#line 200 "accessor_class_list.gperf" {"step_in_units", &grib_accessor_class_step_in_units}, -#line 188 "accessor_class_list.gperf" +#line 189 "accessor_class_list.gperf" {"signed_bits", &grib_accessor_class_signed_bits}, -#line 193 "accessor_class_list.gperf" +#line 194 "accessor_class_list.gperf" {"spd", &grib_accessor_class_spd}, -#line 167 "accessor_class_list.gperf" +#line 168 "accessor_class_list.gperf" {"pad", &grib_accessor_class_pad}, #line 76 "accessor_class_list.gperf" {"data_simple_packing", &grib_accessor_class_data_simple_packing}, @@ -177,7 +178,7 @@ static const struct accessor_class_hash classes[] = #line 79 "accessor_class_list.gperf" {"dirty", &grib_accessor_class_dirty}, {""}, {""}, -#line 197 "accessor_class_list.gperf" +#line 198 "accessor_class_list.gperf" {"statistics_spectral", &grib_accessor_class_statistics_spectral}, #line 78 "accessor_class_list.gperf" {"dictionary", &grib_accessor_class_dictionary}, @@ -187,7 +188,7 @@ static const struct accessor_class_hash classes[] = {""}, #line 112 "accessor_class_list.gperf" {"g2lon", &grib_accessor_class_g2lon}, -#line 205 "accessor_class_list.gperf" +#line 206 "accessor_class_list.gperf" {"to_integer", &grib_accessor_class_to_integer}, #line 127 "accessor_class_list.gperf" {"int16", &grib_accessor_class_int16}, @@ -197,7 +198,7 @@ static const struct accessor_class_hash classes[] = #line 46 "accessor_class_list.gperf" {"data_apply_bitmap", &grib_accessor_class_data_apply_bitmap}, {""}, -#line 184 "accessor_class_list.gperf" +#line 185 "accessor_class_list.gperf" {"section_pointer", &grib_accessor_class_section_pointer}, #line 68 "accessor_class_list.gperf" {"data_jpeg2000_packing", &grib_accessor_class_data_jpeg2000_packing}, @@ -225,32 +226,32 @@ static const struct accessor_class_hash classes[] = #line 109 "accessor_class_list.gperf" {"g2grid", &grib_accessor_class_g2grid}, {""}, -#line 206 "accessor_class_list.gperf" +#line 207 "accessor_class_list.gperf" {"to_string", &grib_accessor_class_to_string}, {""}, {""}, #line 134 "accessor_class_list.gperf" {"iterator", &grib_accessor_class_iterator}, -#line 168 "accessor_class_list.gperf" +#line 169 "accessor_class_list.gperf" {"padding", &grib_accessor_class_padding}, {""}, {""}, -#line 209 "accessor_class_list.gperf" +#line 210 "accessor_class_list.gperf" {"trim", &grib_accessor_class_trim}, {""}, #line 65 "accessor_class_list.gperf" {"data_g2shsimple_packing", &grib_accessor_class_data_g2shsimple_packing}, -#line 174 "accessor_class_list.gperf" +#line 175 "accessor_class_list.gperf" {"raw", &grib_accessor_class_raw}, {""}, #line 82 "accessor_class_list.gperf" {"element", &grib_accessor_class_element}, -#line 169 "accessor_class_list.gperf" +#line 170 "accessor_class_list.gperf" {"padto", &grib_accessor_class_padto}, #line 103 "accessor_class_list.gperf" {"g2_eps", &grib_accessor_class_g2_eps}, {""}, {""}, #line 156 "accessor_class_list.gperf" {"non_alpha", &grib_accessor_class_non_alpha}, -#line 207 "accessor_class_list.gperf" +#line 208 "accessor_class_list.gperf" {"transient", &grib_accessor_class_transient}, #line 14 "accessor_class_list.gperf" {"assert", &grib_accessor_class_assert}, @@ -262,7 +263,7 @@ static const struct accessor_class_hash classes[] = {"data_g2simple_packing", &grib_accessor_class_data_g2simple_packing}, #line 63 "accessor_class_list.gperf" {"data_g2complex_packing", &grib_accessor_class_data_g2complex_packing}, -#line 208 "accessor_class_list.gperf" +#line 209 "accessor_class_list.gperf" {"transient_darray", &grib_accessor_class_transient_darray}, {""}, #line 101 "accessor_class_list.gperf" @@ -277,7 +278,7 @@ static const struct accessor_class_hash classes[] = #line 12 "accessor_class_list.gperf" {"array", &grib_accessor_class_array}, {""}, {""}, {""}, {""}, -#line 175 "accessor_class_list.gperf" +#line 176 "accessor_class_list.gperf" {"rdbtime_guess_date", &grib_accessor_class_rdbtime_guess_date}, #line 67 "accessor_class_list.gperf" {"data_g2simple_packing_with_preprocessing", &grib_accessor_class_data_g2simple_packing_with_preprocessing}, @@ -285,59 +286,59 @@ static const struct accessor_class_hash classes[] = #line 119 "accessor_class_list.gperf" {"global_gaussian", &grib_accessor_class_global_gaussian}, {""}, -#line 186 "accessor_class_list.gperf" +#line 187 "accessor_class_list.gperf" {"sexagesimal2decimal", &grib_accessor_class_sexagesimal2decimal}, #line 139 "accessor_class_list.gperf" {"laplacian", &grib_accessor_class_laplacian}, {""}, -#line 200 "accessor_class_list.gperf" +#line 201 "accessor_class_list.gperf" {"sum", &grib_accessor_class_sum}, {""}, #line 114 "accessor_class_list.gperf" {"gaussian_grid_name", &grib_accessor_class_gaussian_grid_name}, -#line 177 "accessor_class_list.gperf" +#line 178 "accessor_class_list.gperf" {"round", &grib_accessor_class_round}, #line 145 "accessor_class_list.gperf" {"long", &grib_accessor_class_long}, {""}, #line 81 "accessor_class_list.gperf" {"double", &grib_accessor_class_double}, -#line 189 "accessor_class_list.gperf" +#line 190 "accessor_class_list.gperf" {"simple_packing_error", &grib_accessor_class_simple_packing_error}, #line 120 "accessor_class_list.gperf" {"group", &grib_accessor_class_group}, {""}, -#line 172 "accessor_class_list.gperf" +#line 173 "accessor_class_list.gperf" {"position", &grib_accessor_class_position}, #line 136 "accessor_class_list.gperf" {"julian_day", &grib_accessor_class_julian_day}, #line 135 "accessor_class_list.gperf" {"julian_date", &grib_accessor_class_julian_date}, -#line 219 "accessor_class_list.gperf" +#line 220 "accessor_class_list.gperf" {"unsigned", &grib_accessor_class_unsigned}, {""}, {""}, #line 52 "accessor_class_list.gperf" {"data_dummy_field", &grib_accessor_class_data_dummy_field}, {""}, -#line 173 "accessor_class_list.gperf" +#line 174 "accessor_class_list.gperf" {"proj_string", &grib_accessor_class_proj_string}, #line 15 "accessor_class_list.gperf" {"bit", &grib_accessor_class_bit}, #line 17 "accessor_class_list.gperf" {"bits", &grib_accessor_class_bits}, -#line 198 "accessor_class_list.gperf" +#line 199 "accessor_class_list.gperf" {"step_human_readable", &grib_accessor_class_step_human_readable}, #line 71 "accessor_class_list.gperf" {"data_run_length_packing", &grib_accessor_class_data_run_length_packing}, -#line 178 "accessor_class_list.gperf" +#line 179 "accessor_class_list.gperf" {"scale", &grib_accessor_class_scale}, -#line 194 "accessor_class_list.gperf" +#line 195 "accessor_class_list.gperf" {"spectral_truncation", &grib_accessor_class_spectral_truncation}, #line 45 "accessor_class_list.gperf" {"data_2order_packing", &grib_accessor_class_data_2order_packing}, -#line 212 "accessor_class_list.gperf" +#line 213 "accessor_class_list.gperf" {"uint32", &grib_accessor_class_uint32}, -#line 216 "accessor_class_list.gperf" +#line 217 "accessor_class_list.gperf" {"uint8", &grib_accessor_class_uint8}, #line 31 "accessor_class_list.gperf" {"bytes", &grib_accessor_class_bytes}, @@ -347,7 +348,7 @@ static const struct accessor_class_hash classes[] = #line 106 "accessor_class_list.gperf" {"g2bitmap_present", &grib_accessor_class_g2bitmap_present}, {""}, {""}, -#line 195 "accessor_class_list.gperf" +#line 196 "accessor_class_list.gperf" {"sprintf", &grib_accessor_class_sprintf}, {""}, {""}, {""}, #line 18 "accessor_class_list.gperf" @@ -355,12 +356,12 @@ static const struct accessor_class_hash classes[] = #line 50 "accessor_class_list.gperf" {"data_ccsds_packing", &grib_accessor_class_data_ccsds_packing}, {""}, -#line 220 "accessor_class_list.gperf" +#line 221 "accessor_class_list.gperf" {"unsigned_bits", &grib_accessor_class_unsigned_bits}, #line 164 "accessor_class_list.gperf" {"offset_file", &grib_accessor_class_offset_file}, {""}, -#line 213 "accessor_class_list.gperf" +#line 214 "accessor_class_list.gperf" {"uint32_little_endian", &grib_accessor_class_uint32_little_endian}, {""}, #line 89 "accessor_class_list.gperf" @@ -373,9 +374,9 @@ static const struct accessor_class_hash classes[] = {""}, {""}, #line 138 "accessor_class_list.gperf" {"label", &grib_accessor_class_label}, -#line 217 "accessor_class_list.gperf" +#line 218 "accessor_class_list.gperf" {"unexpanded_descriptors", &grib_accessor_class_unexpanded_descriptors}, -#line 214 "accessor_class_list.gperf" +#line 215 "accessor_class_list.gperf" {"uint64", &grib_accessor_class_uint64}, {""}, #line 159 "accessor_class_list.gperf" @@ -399,18 +400,18 @@ static const struct accessor_class_hash classes[] = {"concept", &grib_accessor_class_concept}, #line 41 "accessor_class_list.gperf" {"constant", &grib_accessor_class_constant}, -#line 215 "accessor_class_list.gperf" +#line 216 "accessor_class_list.gperf" {"uint64_little_endian", &grib_accessor_class_uint64_little_endian}, #line 80 "accessor_class_list.gperf" {"divdouble", &grib_accessor_class_divdouble}, -#line 226 "accessor_class_list.gperf" +#line 227 "accessor_class_list.gperf" {"when", &grib_accessor_class_when}, #line 163 "accessor_class_list.gperf" {"octet_number", &grib_accessor_class_octet_number}, {""}, #line 104 "accessor_class_list.gperf" {"g2_mars_labeling", &grib_accessor_class_g2_mars_labeling}, -#line 185 "accessor_class_list.gperf" +#line 186 "accessor_class_list.gperf" {"select_step_template", &grib_accessor_class_select_step_template}, {""}, #line 59 "accessor_class_list.gperf" @@ -422,7 +423,7 @@ static const struct accessor_class_hash classes[] = #line 19 "accessor_class_list.gperf" {"blob", &grib_accessor_class_blob}, {""}, {""}, {""}, -#line 223 "accessor_class_list.gperf" +#line 224 "accessor_class_list.gperf" {"values", &grib_accessor_class_values}, {""}, {""}, {""}, {""}, #line 60 "accessor_class_list.gperf" @@ -432,18 +433,18 @@ static const struct accessor_class_hash classes[] = {""}, {""}, #line 146 "accessor_class_list.gperf" {"long_vector", &grib_accessor_class_long_vector}, -#line 201 "accessor_class_list.gperf" +#line 202 "accessor_class_list.gperf" {"suppressed", &grib_accessor_class_suppressed}, #line 121 "accessor_class_list.gperf" {"gts_header", &grib_accessor_class_gts_header}, -#line 204 "accessor_class_list.gperf" +#line 205 "accessor_class_list.gperf" {"to_double", &grib_accessor_class_to_double}, {""}, {""}, #line 144 "accessor_class_list.gperf" {"local_definition", &grib_accessor_class_local_definition}, #line 58 "accessor_class_list.gperf" {"data_g1secondary_bitmap", &grib_accessor_class_data_g1secondary_bitmap}, -#line 221 "accessor_class_list.gperf" +#line 222 "accessor_class_list.gperf" {"validity_date", &grib_accessor_class_validity_date}, #line 143 "accessor_class_list.gperf" {"library_version", &grib_accessor_class_library_version}, @@ -466,7 +467,7 @@ static const struct accessor_class_hash classes[] = {"data_g1second_order_row_by_row_packing", &grib_accessor_class_data_g1second_order_row_by_row_packing}, #line 151 "accessor_class_list.gperf" {"md5", &grib_accessor_class_md5}, -#line 222 "accessor_class_list.gperf" +#line 223 "accessor_class_list.gperf" {"validity_time", &grib_accessor_class_validity_time}, #line 130 "accessor_class_list.gperf" {"int32_little_endian", &grib_accessor_class_int32_little_endian}, @@ -478,7 +479,7 @@ static const struct accessor_class_hash classes[] = {""}, {""}, #line 74 "accessor_class_list.gperf" {"data_sh_unpacked", &grib_accessor_class_data_sh_unpacked}, -#line 225 "accessor_class_list.gperf" +#line 226 "accessor_class_list.gperf" {"vector", &grib_accessor_class_vector}, #line 20 "accessor_class_list.gperf" {"budgdate", &grib_accessor_class_budgdate}, @@ -491,14 +492,14 @@ static const struct accessor_class_hash classes[] = #line 137 "accessor_class_list.gperf" {"ksec1expver", &grib_accessor_class_ksec1expver}, {""}, -#line 171 "accessor_class_list.gperf" +#line 172 "accessor_class_list.gperf" {"padtomultiple", &grib_accessor_class_padtomultiple}, #line 150 "accessor_class_list.gperf" {"mars_step", &grib_accessor_class_mars_step}, #line 126 "accessor_class_list.gperf" {"ifs_param", &grib_accessor_class_ifs_param}, {""}, -#line 191 "accessor_class_list.gperf" +#line 192 "accessor_class_list.gperf" {"smart_table", &grib_accessor_class_smart_table}, {""}, #line 149 "accessor_class_list.gperf" @@ -507,7 +508,7 @@ static const struct accessor_class_hash classes[] = #line 22 "accessor_class_list.gperf" {"bufr_data_element", &grib_accessor_class_bufr_data_element}, {""}, {""}, -#line 192 "accessor_class_list.gperf" +#line 193 "accessor_class_list.gperf" {"smart_table_column", &grib_accessor_class_smart_table_column}, {""}, #line 21 "accessor_class_list.gperf" @@ -541,15 +542,15 @@ static const struct accessor_class_hash classes[] = #line 153 "accessor_class_list.gperf" {"message_copy", &grib_accessor_class_message_copy}, {""}, {""}, -#line 170 "accessor_class_list.gperf" +#line 171 "accessor_class_list.gperf" {"padtoeven", &grib_accessor_class_padtoeven}, {""}, {""}, -#line 210 "accessor_class_list.gperf" +#line 211 "accessor_class_list.gperf" {"uint16", &grib_accessor_class_uint16}, {""}, {""}, #line 154 "accessor_class_list.gperf" {"missing", &grib_accessor_class_missing}, -#line 224 "accessor_class_list.gperf" +#line 225 "accessor_class_list.gperf" {"variable", &grib_accessor_class_variable}, {""}, {""}, #line 86 "accessor_class_list.gperf" @@ -561,7 +562,7 @@ static const struct accessor_class_hash classes[] = #line 36 "accessor_class_list.gperf" {"codeflag", &grib_accessor_class_codeflag}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 211 "accessor_class_list.gperf" +#line 212 "accessor_class_list.gperf" {"uint16_little_endian", &grib_accessor_class_uint16_little_endian}, #line 37 "accessor_class_list.gperf" {"codetable", &grib_accessor_class_codetable}, @@ -595,10 +596,10 @@ static const struct accessor_class_hash classes[] = #line 161 "accessor_class_list.gperf" {"number_of_values_data_raw_packing", &grib_accessor_class_number_of_values_data_raw_packing}, {""}, {""}, {""}, {""}, -#line 179 "accessor_class_list.gperf" +#line 180 "accessor_class_list.gperf" {"scale_values", &grib_accessor_class_scale_values}, {""}, -#line 218 "accessor_class_list.gperf" +#line 219 "accessor_class_list.gperf" {"unpack_bufr_values", &grib_accessor_class_unpack_bufr_values}, {""}, {""}, {""}, #line 85 "accessor_class_list.gperf" @@ -617,10 +618,10 @@ static const struct accessor_class_hash classes[] = {""}, {""}, #line 100 "accessor_class_list.gperf" {"g1verificationdate", &grib_accessor_class_g1verificationdate}, -#line 166 "accessor_class_list.gperf" +#line 167 "accessor_class_list.gperf" {"pack_bufr_values", &grib_accessor_class_pack_bufr_values}, {""}, {""}, -#line 176 "accessor_class_list.gperf" +#line 177 "accessor_class_list.gperf" {"reference_value_error", &grib_accessor_class_reference_value_error}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -638,7 +639,9 @@ static const struct accessor_class_hash classes[] = {""}, {""}, #line 10 "accessor_class_list.gperf" {"abstract_long_vector", &grib_accessor_class_abstract_long_vector}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 166 "accessor_class_list.gperf" + {"optimal_step_units", &grib_accessor_class_optimal_step_units}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, @@ -686,19 +689,20 @@ static const struct accessor_class_hash classes[] = {"g1forecastmonth", &grib_accessor_class_g1forecastmonth} }; -static const struct accessor_class_hash* grib_accessor_classes_hash (const char *str, size_t len) +const struct accessor_class_hash * +grib_accessor_classes_hash (register const char *str, register size_t len) { - unsigned int key = grib_accessor_classes_get_id (str, len); - -#ifdef DEBUG + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { - const char *s; - Assert( len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH ); - Assert( key <= MAX_HASH_VALUE ); - s = classes[key].name; - Assert( *str == *s && strcmp(str + 1, s + 1)==0 ); - } -#endif + register unsigned int key = grib_accessor_classes_get_id (str, len); - return &classes[key]; + if (key <= MAX_HASH_VALUE) + { + register const char *s = classes[key].name; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &classes[key]; + } + } + return 0; } diff --git a/src/grib_accessor_factory.h b/src/grib_accessor_factory.h index a706fc95c..9dced7940 100644 --- a/src/grib_accessor_factory.h +++ b/src/grib_accessor_factory.h @@ -155,6 +155,7 @@ { "octet_number", &grib_accessor_class_octet_number, }, { "offset_file", &grib_accessor_class_offset_file, }, { "offset_values", &grib_accessor_class_offset_values, }, +{ "optimal_step_units", &grib_accessor_class_optimal_step_units, }, { "pack_bufr_values", &grib_accessor_class_pack_bufr_values, }, { "pad", &grib_accessor_class_pad, }, { "padding", &grib_accessor_class_padding, }, diff --git a/src/grib_accessor_factory_hash_list b/src/grib_accessor_factory_hash_list index 0abb60a46..e8f526500 100644 --- a/src/grib_accessor_factory_hash_list +++ b/src/grib_accessor_factory_hash_list @@ -156,6 +156,7 @@ octahedral_gaussian, &grib_accessor_class_octahedral_gaussian octet_number, &grib_accessor_class_octet_number offset_file, &grib_accessor_class_offset_file offset_values, &grib_accessor_class_offset_values +optimal_step_units, &grib_accessor_class_optimal_step_units pack_bufr_values, &grib_accessor_class_pack_bufr_values pad, &grib_accessor_class_pad padding, &grib_accessor_class_padding diff --git a/src/step.cc b/src/step.cc index 4aa810a08..d1f1faa5e 100644 --- a/src/step.cc +++ b/src/step.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include "step.h" @@ -18,41 +19,205 @@ std::vector UnitType::unitOrder = { }; -std::string parse_step(std::string step) { - if (step.find_first_of("smhdMYC") == std::string::npos) { - step += "h"; +Step step_from_string(std::string step) { + std::regex re("([0-9.]+)([smhDMYC]?)"); + std::smatch match; + if (std::regex_match(step, match, re)) { + if (match.size() == 3) { + std::string value = match[1]; + std::string unit = match[2]; + if (unit.size() == 0) { + unit = "h"; + } + return Step{std::stod(value), UnitType{unit}}; + } } - return step; + throw std::runtime_error("Could not parse step: " + step); +} + +std::vector parseRange(const std::string& range_str) { + std::vector steps; + std::string::size_type pos = 0; + std::string::size_type prev = 0; + while ((pos = range_str.find("-", prev)) != std::string::npos) { + steps.push_back(step_from_string(range_str.substr(prev, pos - prev))); + prev = pos + 1; + } + steps.push_back(step_from_string(range_str.substr(prev))); + return steps; } -std::pair, Step> findCommonUnits(const Step& startStep, const Step& endStep) { - Step a = startStep; - Step b = endStep; - - if (a.value_ == 0 || b.value_ == 0) { - if (a.value_ == 0 && b.value_ == 0) { - UnitType unit = a.unit_ > b.unit_ ? a.unit_ : b.unit_; - a.setUnit(unit); - b.setUnit(unit); - } - else if (a.value_ == 0) { - a.setUnit(b.unit_); - } - else if (b.value_ == 0) { - b.setUnit(a.unit_); - } - return {a, b}; +bool Step::operator==(const Step& other) const { + if ((internal_value_ == other.internal_value_) && (internal_unit_ == other.internal_unit_)) { + return true; } + return false; +} - auto it = std::find_if(UnitType::unitOrder.begin(), UnitType::unitOrder.end(), [&](const auto& e) { - return e == a.unit().to_value() || e == b.unit().to_value(); - }); +Step Step::operator+(const Step& step) { + Step tmp = step; + auto [a, b] = findCommonUnits(this->optimizeUnit(), tmp.optimizeUnit()); + assert(a.internal_unit_ == b.internal_unit_); + return Step(a.internal_value_ + b.internal_value_, a.internal_unit_); +} - assert(it != UnitType::unitOrder.end()); +Step Step::operator-(const Step& step) { + Step tmp = step; + auto [a, b] = findCommonUnits(this->optimizeUnit(), tmp.optimizeUnit()); + assert(a.internal_unit_ == b.internal_unit_); + if (a.internal_value_ < b.internal_value_) { + throw std::runtime_error("Negative step not supported"); + } + return Step(a.internal_value_ - b.internal_value_, a.internal_unit_); +} - a.setUnit(*it); - b.setUnit(*it); +std::pair findCommonUnits(const Step& startStep, const Step& endStep) { + Step a = startStep; + Step b = endStep; + + if (a.internal_value_ == 0 && b.internal_value_ == 0) { + UnitType unit = a.internal_unit_ > b.internal_unit_ ? a.internal_unit_ : b.internal_unit_; + b.internal_unit_ = unit; + b.unit_ = unit; + a.internal_unit_ = unit; + a.unit_ = unit; + } + else if (b.internal_value_ == 0) { + b.internal_unit_ = a.internal_unit_; + b.unit_ = a.internal_unit_; + a.unit_ = a.internal_unit_; + a.recalculateValue(); + } + else if (a.internal_value_ == 0) { + a.internal_unit_ = b.internal_unit_; + a.unit_ = b.internal_unit_; + b.unit_ = b.internal_unit_; + b.recalculateValue(); + } + else { + // Find the highest common unit + auto it = std::find_if(UnitType::unitOrder.begin(), UnitType::unitOrder.end(), [&](const auto& e) { + return e == a.unit().toValue() || e == b.unit().toValue(); + }); + + assert(it != UnitType::unitOrder.end()); + + a.setUnit(*it); + b.setUnit(*it); + a.recalculateValue(); + b.recalculateValue(); + assert(a.internal_unit_ == b.internal_unit_); + } return {a, b}; } + +void Step::sanityCheck() const { + static_assert(sizeof(int) == 4, "int is not 4 bytes"); + if (!(internal_value_ >= std::numeric_limits::min() && internal_value_ <= std::numeric_limits::max())) { + throw std::out_of_range("Step is out of range."); + } +} + + +void Step::initLong(long value, const UnitType& unit) { + internal_value_ = value; + internal_unit_ = unit; + unit_ = internal_unit_; + sanityCheck(); +} + +void Step::initDouble(double value, const UnitType& unit) { + long seconds = UnitType::getConverter().unit_to_duration(unit.toValue()); + initLong(static_cast(value * seconds), UnitType{Unit::SECOND}); + optimizeUnit(); +} + +Step::Step(double value, const UnitType& unit) : internal_unit_{unit}, unit_{internal_unit_} {initDouble(value, unit);} +Step::Step(double value, Unit unit) {initDouble(value, UnitType{unit});} +Step::Step(double value, long unit) {initDouble(value, UnitType{unit});} +Step::Step(double value, const std::string& unit) {initDouble(value, UnitType{unit});} + +Step::Step(long value, const UnitType& unit) { initLong(value, unit);} +Step::Step(long value, Unit unit) {initLong(value, UnitType{unit});} +Step::Step(long value, long unit) {initLong(value, UnitType{unit});} +Step::Step(long value, const std::string& unit) {initLong(value, UnitType{unit});} + +Step::Step(const std::string& str) { + //size_t pos = str.find_first_of("smhDMYC"); + size_t pos = str.find_first_of("smh"); + if (pos == std::string::npos) { + throw std::runtime_error("Unknown unit."); + } + std::string v_str = str.substr(0, pos); + std::string u_str = str.substr(pos); + double v = std::stod(v_str); + + initDouble(v, UnitType{u_str}); +} + + +Step& Step::optimizeUnit() { + if (internal_value_ == 0) { + return *this; + } + + unit_ = internal_unit_; + Seconds duration(0); + switch (internal_unit_.toValue()) { + case Unit::SECOND: + duration = Seconds(internal_value_); + break; + case Unit::MINUTE: + duration = Minutes(internal_value_); + break; + case Unit::HOUR: + duration = Hours(internal_value_); + break; + case Unit::DAY: + duration = Days(internal_value_); + break; + case Unit::MONTH: + duration = Months(internal_value_); + break; + default: + std::string msg = "Unknown unit: " + internal_unit_.toString(); + throw std::runtime_error(msg); + } + + Seconds d = std::chrono::duration_cast>(duration); + + for (auto it = UnitType::unitOrder.rbegin(); it != UnitType::unitOrder.rend(); ++it) { + long multiplier = UnitType::getConverter().unit_to_duration(*it); + if (d.count() % multiplier == 0) { + internal_value_ = duration.count() / multiplier; + internal_unit_ = *it; + unit_ = *it; + return *this; + } + } + + return *this; +} + +Step& Step::setUnit(const std::string& unit_name) { + unit_ = UnitType{unit_name}; + return *this; +} + +Step& Step::setUnit(long unit_code) { + unit_ = UnitType{unit_code}; + return *this; +} + +Step& Step::setUnit(const UnitType& new_unit) { + unit_ = new_unit; + return *this; +} + +Step& Step::setUnit(const Unit new_unit) { + unit_ = new_unit; + return *this; +} + diff --git a/src/step.h b/src/step.h index 45514441d..52c8b9f17 100644 --- a/src/step.h +++ b/src/step.h @@ -12,6 +12,8 @@ #include #include #include +#include +#include template using Minutes = std::chrono::duration>; @@ -52,31 +54,34 @@ enum class Unit { class UnitType { public: - explicit UnitType() : value_(Unit::HOUR) {} - explicit UnitType(Unit unit_value) : value_(unit_value) {} - explicit UnitType(const std::string& unit_value) {value_ = map_.name_to_unit(unit_value);} - explicit UnitType(long unit_value) {value_ = map_.long_to_unit(unit_value);} + explicit UnitType() : internal_value_(Unit::HOUR) {} + explicit UnitType(Unit unit_value) : internal_value_(unit_value) {} + explicit UnitType(const std::string& unit_value) {internal_value_ = map_.name_to_unit(unit_value);} + explicit UnitType(long unit_value) {internal_value_ = map_.long_to_unit(unit_value);} + + bool operator>(const UnitType& other) const {return map_.unit_to_duration(internal_value_) > map_.unit_to_duration(other.internal_value_);} + bool operator==(const Unit value) const {return map_.unit_to_duration(internal_value_) == map_.unit_to_duration(value);} + bool operator==(const UnitType& unit) const {return map_.unit_to_duration(internal_value_) == map_.unit_to_duration(unit.internal_value_);} + bool operator!=(const UnitType& unit) const {return !(*this == unit);} + bool operator!=(const Unit value) const {return !(*this == value);} - bool operator>(const UnitType& other) const {return map_.unit_to_duration(value_) > map_.unit_to_duration(other.value_);} - bool operator==(const Unit value) const {return map_.unit_to_duration(value_) == map_.unit_to_duration(value);} - bool operator==(const UnitType& unit) const {return map_.unit_to_duration(value_) == map_.unit_to_duration(unit.value_);} UnitType& operator=(const Unit value) { - value_ = value; + internal_value_ = value; return *this; } - std::string to_string() const { - if ((value_ == Unit::HOUR) && hide_hour_unit_) { + std::string toString() const { + if ((internal_value_ == Unit::HOUR) && hide_hour_unit_) { return ""; } else { - return map_.unit_to_name(value_); + return map_.unit_to_name(internal_value_); } } - long to_long() const {return map_.unit_to_long(value_);} - Unit to_value() const {return value_;} - void hide_hour_unit() {hide_hour_unit_ = true;} - void show_hour_unit() {hide_hour_unit_ = false;} + long toLong() const {return map_.unit_to_long(internal_value_);} + Unit toValue() const {return internal_value_;} + void hideHourUnit() {hide_hour_unit_ = true;} + void showHourUnit() {hide_hour_unit_ = false;} static std::vector unitOrder; private: @@ -147,257 +152,166 @@ private: }; - Unit value_; + Unit internal_value_; static Map map_; public: - static Map& get_converter() {return map_;} + static Map& getConverter() {return map_;} }; - - - -template class Step { public: - // Constructors - Step() : value_(0), unit_(Unit::SECOND) {} - Step(T value, Unit unit); - Step(T value, const UnitType& unit); - Step(T value, long unit); - Step(T value, const std::string& unit); + Step() : internal_value_(0), internal_unit_(Unit::SECOND) {} + Step(double value, const UnitType& unit); + Step(double value, Unit unit); + Step(double value, long unit); + Step(double value, const std::string& unit); + + Step(long value, const UnitType& unit); + Step(long value, Unit unit); + Step(long value, long unit); + Step(long value, const std::string& unit); explicit Step(const std::string& str); // Getters - T value() const { return value_; } + template T value() const; UnitType unit() const { return unit_; } // Setters - Step& setUnit(long new_unit); - Step& setUnit(const std::string& new_unit); - Step& setUnit(const Unit new_unit); - Step& setUnit(const UnitType& new_unit); + Step& setUnit(long new_unit); + Step& setUnit(const std::string& new_unit); + Step& setUnit(const Unit new_unit); + Step& setUnit(const UnitType& new_unit); // Operators - bool operator==(const Step& other) const; - Step operator+(const Step& step); - operator Step() const {return Step{static_cast(value_), unit_};} + bool operator==(const Step& other) const; + bool operator!=(const Step& other) const; + Step operator+(const Step& step); + Step operator-(const Step& step); // Methods - Step& optimizeUnit(); - friend std::pair, Step> findCommonUnits(const Step& startStep, const Step& endStep); - void hide_hour_unit() {unit_.hide_hour_unit();} - void show_hour_unit() {unit_.show_hour_unit();} + Step& optimizeUnit(); + friend std::pair findCommonUnits(const Step& startStep, const Step& endStep); + void hideHourUnit() { + internal_unit_.hideHourUnit(); + unit_.hideHourUnit(); + } + void showHourUnit() { + internal_unit_.showHourUnit(); + unit_.showHourUnit(); + } + + std::string toString() const { + std::stringstream ss; + if (value() == value()) { + ss << value() << unit_.toString(); + } else { + ss << value() << unit_.toString(); + } + return ss.str(); + } private: - T value_; + void initLong(long value, const UnitType& unit); + void initDouble(double value, const UnitType& unit); + void sanityCheck() const; + Step& recalculateValue() { + if (internal_value_ == 0) { + internal_unit_ = unit_; + return *this; + } + + Seconds secs(0); + switch (internal_unit_.toValue()) { + case Unit::SECOND: + secs = Seconds(internal_value_); + break; + case Unit::MINUTE: + secs = Minutes(internal_value_); + break; + case Unit::HOUR: + secs = Hours(internal_value_); + break; + case Unit::DAY: + secs = Days(internal_value_); + break; + case Unit::MONTH: + secs = Months(internal_value_); + break; + default: + std::string msg = "Unknown unit: " + internal_unit_.toString(); + throw std::runtime_error(msg); + } + + long multiplier = UnitType::getConverter().unit_to_duration(unit_.toValue()); + internal_value_ = secs.count() / multiplier; + internal_unit_ = unit_; + + return *this; + } + + long internal_value_; + UnitType internal_unit_; UnitType unit_; }; +Step step_from_string(std::string step); +std::vector parseRange(const std::string& range_str); +std::pair findCommonUnits(const Step& startStep, const Step& endStep); -std::string parse_step(std::string step); - -template -bool Step::operator==(const Step& other) const { - if ((value_ == other.value_) && (unit_ == other.unit_)) { - return true; +template T Step::value() const { + if (internal_value_ == 0) { + return internal_value_; } - return false; -} - -template -Step Step::operator+(const Step& step) { - auto [a, b] = findCommonUnits(*this, step); - return Step(a.value_ + b.value_, a.unit_); -} - -std::pair, Step> findCommonUnits(const Step& startStep, const Step& endStep); - - -template std::vector> parse_range(const std::string& range_str) { - std::vector> steps; - std::string::size_type pos = 0; - std::string::size_type prev = 0; - while ((pos = range_str.find("-", prev)) != std::string::npos) { - std::string token = parse_step(range_str.substr(prev, pos - prev)); - if (token.size() > 0) { - steps.push_back(Step(token)); - } - prev = pos + 1; - } - std::string token = parse_step(range_str.substr(prev)); - if (token.size() > 0) { - steps.push_back(Step(token)); - } - return steps; -} - - -template -Step::Step(T value, Unit unit) : value_{value}, unit_{UnitType{unit}} { - static_assert(sizeof(int) == 4, "int is not 4 bytes"); - if (!(value >= 0 && value <= std::numeric_limits::max())) { - throw std::out_of_range("Step is out of range."); - } -} - - -template -Step::Step(T value, long unit) : value_{value}, unit_{UnitType{unit}} { - static_assert(sizeof(int) == 4, "int is not 4 bytes"); - if (!(value >= 0 && value <= std::numeric_limits::max())) { - throw std::out_of_range("Step is out of range."); - } -} - -template -Step::Step(T value, const std::string& unit) : value_{value}, unit_{UnitType{unit}} { - static_assert(sizeof(int) == 4, "int is not 4 bytes"); - if (!(value >= 0 && value <= std::numeric_limits::max())) { - throw std::out_of_range("Step is out of range."); - } -} - -template -Step::Step(const std::string& str) { - size_t pos = str.find_first_of("smhdMYC"); - if (pos == std::string::npos) { - throw std::runtime_error("Unknown unit."); - } - std::string v_str = str.substr(0, pos); - std::string u_str = str.substr(pos); - int v = std::stoi(v_str); - value_ = v; - unit_ = UnitType{u_str}; -} - -template -Step::Step(T value, const UnitType& u) { - static_assert(sizeof(int) == 4, "int is not 4 bytes"); - if (!(value >= 0 && value <= std::numeric_limits::max())) { - throw std::out_of_range("Step is out of range."); - } - value_ = value; - unit_ = u; -} - -template -Step& Step::optimizeUnit() { - if (value_ == 0) { - return *this; - } - - Seconds duration(0); - switch (unit_.to_value()) { - case Unit::SECOND: - duration = Seconds(value_); - break; - case Unit::MINUTE: - duration = Minutes(value_); - break; - case Unit::HOUR: - duration = Hours(value_); - break; - case Unit::DAY: - duration = Days(value_); - break; - case Unit::MONTH: - duration = Months(value_); - break; - default: - std::string msg = "Unknown unit: " + unit_.to_string(); - throw std::runtime_error(msg); - } - - Seconds d = std::chrono::duration_cast>(duration); - - for (auto it = UnitType::unitOrder.rbegin(); it != UnitType::unitOrder.rend(); ++it) { - long multiplier = UnitType::get_converter().unit_to_duration(*it); - if (d.count() % multiplier == 0) { - value_ = duration.count() / multiplier; - unit_ = *it; - return *this; - } - } - - return *this; -} - -template -Step& Step::setUnit(const std::string& unit_name) { - setUnit(UnitType{unit_name}); - return *this; -} - -template -Step& Step::setUnit(long unit_code) { - setUnit(UnitType{unit_code}); - return *this; -} - -template -Step& Step::setUnit(const UnitType& new_unit) { - setUnit(new_unit.to_value()); - return *this; -} - - -template -Step& Step::setUnit(const Unit new_unit) { - if (value_ == 0) { - unit_ = new_unit; - return *this; - } - if (unit_ == new_unit) { - return *this; + if (internal_unit_ == unit_) { + return internal_value_; } Seconds duration(0); - switch (unit_.to_value()) { + switch (internal_unit_.toValue()) { case Unit::SECOND: - duration = Seconds(value_); + duration = Seconds(internal_value_); break; case Unit::MINUTE: - duration = Minutes(value_); + duration = Minutes(internal_value_); break; case Unit::HOUR: - duration = Hours(value_); + duration = Hours(internal_value_); break; case Unit::DAY: - duration = Days(value_); + duration = Days(internal_value_); break; case Unit::MONTH: - duration = Months(value_); + duration = Months(internal_value_); break; default: - std::string msg = "Unknown unit: " + unit_.to_string(); + std::string msg = "Unknown unit: " + internal_unit_.toString(); throw std::runtime_error(msg); } - switch (new_unit) { + T value = 0; + switch (unit_.toValue()) { case Unit::SECOND: - value_ = duration.count(); + value = duration.count(); break; case Unit::MINUTE: - value_ = std::chrono::duration_cast>(duration).count(); + value = std::chrono::duration_cast>(duration).count(); break; case Unit::HOUR: - value_ = std::chrono::duration_cast>(duration).count(); + value = std::chrono::duration_cast>(duration).count(); break; case Unit::DAY: - value_ = std::chrono::duration_cast>(duration).count(); + value = std::chrono::duration_cast>(duration).count(); break; case Unit::MONTH: - value_ = std::chrono::duration_cast>(duration).count(); + value = std::chrono::duration_cast>(duration).count(); break; default: - std::string msg = "Unknown unit: " + UnitType{new_unit}.to_string(); + std::string msg = "Unknown unit: " + UnitType{unit_}.toString(); throw std::runtime_error(msg); } - unit_ = new_unit; - - return *this; + return value; } diff --git a/src/step_utilities.cc b/src/step_utilities.cc index b216d9d57..575ae8384 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -1,7 +1,7 @@ +//#include "step_range.h" #include "step_utilities.h" - -std::optional> getStep(grib_handle* h, const std::string& value_key, const std::string& unit_key){ +std::optional getStep(grib_handle* h, const std::string& value_key, const std::string& unit_key){ if (grib_is_defined(h, unit_key.c_str()) && grib_is_defined(h, value_key.c_str())) { long unit = 0; if (grib_get_long_internal(h, unit_key.c_str(), &unit) != GRIB_SUCCESS) @@ -11,7 +11,7 @@ std::optional> getStep(grib_handle* h, const std::string& value_key, if (grib_get_long_internal(h, value_key.c_str(), &value) != GRIB_SUCCESS) return {}; - return Step(value, unit); + return Step(value, unit); } else { return {}; @@ -19,28 +19,27 @@ std::optional> getStep(grib_handle* h, const std::string& value_key, } -std::optional> getForecastTime(grib_handle* h) { - return getStep(h, "forecastTime", "indicatorOfUnitOfTimeRange"); -} +//std::optional getForecastTime(grib_handle* h) { +// return getStep(h, "forecastTime", "indicatorOfUnitOfTimeRange"); +//} -std::optional> getLengthOfTimeRange(grib_handle* h) { - return getStep(h, "lengthOfTimeRange", "indicatorOfUnitForTimeRange"); -} +//std::optional getLengthOfTimeRange(grib_handle* h) { +// return getStep(h, "lengthOfTimeRange", "indicatorOfUnitForTimeRange"); +//} -std::pair, Step> getTimeRange(grib_handle* h) { - auto forecast_time = getForecastTime(h); - auto length_of_time_range = getLengthOfTimeRange(h); - return {forecast_time.value(), forecast_time.value() + length_of_time_range.value_or(Step())}; -} - +//StepRange getTimeRange(grib_handle* h) { +// auto forecast_time = getForecastTime(h); +// auto length_of_time_range = getLengthOfTimeRange(h); +// return StepRange{forecast_time.value_or(Step{}), forecast_time.value_or(Step{}) + length_of_time_range.value_or(Step{})}; +//} bool futureOutputEnabled(grib_handle* h) { - int ret = 0; size_t stepOutputFormatSize = 128; char stepOutputFormat[stepOutputFormatSize]; + int ret = 0; if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) return ret; return strcmp(stepOutputFormat, "future") == 0; diff --git a/src/step_utilities.h b/src/step_utilities.h index 21ec426db..fddcd1f9c 100644 --- a/src/step_utilities.h +++ b/src/step_utilities.h @@ -2,43 +2,13 @@ #include "grib_api_internal.h" #include "step.h" - #include +//#include "step_range.h" -std::optional> getStep(grib_handle* h, const std::string& value_key, const std::string& unit_key); -std::optional> getForecastTime(grib_handle* h); -std::optional> getLengthOfTimeRange(grib_handle* h); -std::pair, Step> getTimeRange(grib_handle* h); -//std::pair, Step> getOptTimeRange(grib_handle* h); + +std::optional getStep(grib_handle* h, const std::string& value_key, const std::string& unit_key); +//std::optional getForecastTime(grib_handle* h); +//std::optional getLengthOfTimeRange(grib_handle* h); +//StepRange getTimeRange(grib_handle* h); bool futureOutputEnabled(grib_handle* h); -template int getOptTimeRange(grib_handle* h, Step& s_a, Step& s_b); -//std::pair, Step> getOptTimeRange(grib_handle* h) { - -template -int getOptTimeRange(grib_handle* h, Step& s_a, Step& s_b) { - auto [step_a, step_b] = getTimeRange(h); - - long unit_code = 0; - if (grib_get_long_internal(h, "stepUnits", &unit_code) != GRIB_SUCCESS) - return {}; - - UnitType wanted_unit{unit_code}; - try { - if (wanted_unit == Unit::MISSING) { - std::tie(s_a, s_b) = findCommonUnits(step_a.optimizeUnit(), step_b.optimizeUnit()); - } - else { - s_a = static_cast>(step_a).setUnit(unit_code); - s_b = static_cast>(step_b).setUnit(unit_code); - } - } - catch (...) { - return GRIB_INVALID_ARGUMENT; - } - - s_a.hide_hour_unit(); - s_b.hide_hour_unit(); - return GRIB_SUCCESS; -} - diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index a46f111a1..261f4bc13 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -35,12 +35,103 @@ grib_check_key_equals() echo "Key(s): '$a_params'" echo "Expected: '$a_expected'" echo "Result: '$a_result'" + ${tools_dir}/grib_dump -O $a_file | grep -E "indicatorOfUnitOfTimeRange|lengthOfTimeRange|indicatorOfUnitForTimeRange|forecastTime" exit 1 fi } label="grib_ecc-1620" temp=temp.$label +temp2=temp_2.$label + + + +### CHECK: grib_set - endStep + stepUnits +fn="${data_dir}/reduced_gaussian_sub_area.grib2" +low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" +${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=1,indicatorOfUnitForTimeRange=D $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "24 h 1 D" + +# Use range unit: hour +${tools_dir}/grib_set -y -s endStep:d=30 $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 6 h" +${tools_dir}/grib_set -y -s endStep:d=24.5 $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 30 m" + +# Use stepUnits +${tools_dir}/grib_set -y -s endStep:s=30h $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 6 h" +${tools_dir}/grib_set -y -s endStep:s=24.5h $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 30 m" +${tools_dir}/grib_set -y -s endStep:s=88200s $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 30 m" +${tools_dir}/grib_set -y -s endStep:s=1446.65m $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 399 s" +${tools_dir}/grib_set -y -s endStep:s=24024 $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 1000 D" + +# Use range unit: hour +${tools_dir}/grib_set -y -s startStep:d=5 $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 1 D" +${tools_dir}/grib_set -y -s startStep:d=4.5 $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "270 m 1 D" + +# Use stepUnits +${tools_dir}/grib_set -y -s startStep:s=5h $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 1 D" +${tools_dir}/grib_set -y -s startStep:s=4.5h $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "270 m 1 D" +${tools_dir}/grib_set -y -s startStep:s=240s $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "4 m 1 D" +${tools_dir}/grib_set -y -s startStep:s=0.65m $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "39 s 1 D" +${tools_dir}/grib_set -y -s startStep:s=2 $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "2 h 1 D" + + + + + +${tools_dir}/grib_set -y -s stepRange:s=5h-30h $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 25 h" +grib_check_key_equals $temp2 "-y -p stepRange:s" "5-30" + +${tools_dir}/grib_set -y -s stepRange:s=5-30 $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 25 h" +grib_check_key_equals $temp2 "-y -p stepRange:s" "5-30" + +${tools_dir}/grib_set -y -s stepRange:s=60m-120m $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "1 h 1 h" +grib_check_key_equals $temp2 "-y -p stepRange:s" "1-2" + +${tools_dir}/grib_set -y -s stepRange:s=60s-120s $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "1 m 1 m" +grib_check_key_equals $temp2 "-y -p stepRange:s" "1m-2m" + +${tools_dir}/grib_set -y -s stepRange:s=60m-121m $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "1 h 61 m" +grib_check_key_equals $temp2 "-y -p stepRange:s" "60m-121m" + +${tools_dir}/grib_set -y -s stepRange:s=62D-122D $temp $temp2 +grib_check_key_equals $temp2 "-y -p $low_level_keys" "1488 h 60 D" +grib_check_key_equals $temp2 "-y -p stepRange:s" "1488-2928" +exit + +#${tools_dir}/grib_set -s $fn $temp + +#fn="${data_dir}/reduced_gaussian_surface.grib2" +#low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s" +#keys__="step" +#keys_s="step:s" +#keys_i="step:i" +#keys_d="step:d" + + +#${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp +#${tools_dir}/grib_set -s step:d=10 $fn $temp +#grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=s" "10m" +#exit + fn="${data_dir}/reduced_gaussian_surface.grib2" @@ -52,15 +143,21 @@ keys_d="step:d" ${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp -#grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=s" "3540" -#grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=m" "59" -#grib_expect_failure $temp "-y -p $keys__ -s stepUnits=h" # TODO(EB): check behaviour -#exit -#grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=s" "3540s" -#grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=m" "59m" -grib_expect_failure $temp "-y -p $keys_s -s stepUnits=h" -exit +grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=s" "3540" +grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=m" "59" +grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=h" "0" # TODO(EB): check behaviour (should be 0.983333) +grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=s" "3540s" +grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=m" "59m" +grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=h" "0.983333" # TODO(EB): check behaviour +grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=s" "3540" +grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=m" "59" +grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=h" "0" # TODO(EB): check behaviour +grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=s" "3540" +grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=m" "59" +grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=h" "0.983333" # TODO(EB): check behaviour + +${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=s" "0" grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=m" "0" grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=h" "0" @@ -68,8 +165,6 @@ grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=s" "0" grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=m" "0" grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=h" "0" -exit - fn="${data_dir}/reduced_gaussian_surface.grib2" @@ -80,29 +175,29 @@ keys_i="step:i" keys_d="step:d" -#${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m $fn $temp -#grib_check_key_equals $temp "-p $low_level_keys" "0 m" -#grib_check_key_equals $temp "-p $keys__" "0" -#grib_check_key_equals $temp "-y -p $keys__" "0" -#grib_check_key_equals $temp "-p $keys_s" "0" -#grib_check_key_equals $temp "-y -p $keys_s" "0m" -#grib_check_key_equals $temp "-p $keys_i" "0" -#grib_check_key_equals $temp "-y -p $keys_i" "0" -#grib_check_key_equals $temp "-p $keys_d" "0" -#grib_check_key_equals $temp "-y -p $keys_d" "0" +${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 m" +grib_check_key_equals $temp "-p $keys__" "0" +grib_check_key_equals $temp "-y -p $keys__" "0" +grib_check_key_equals $temp "-p $keys_s" "0" +grib_check_key_equals $temp "-y -p $keys_s" "0m" +grib_check_key_equals $temp "-p $keys_i" "0" +grib_check_key_equals $temp "-y -p $keys_i" "0" +grib_check_key_equals $temp "-p $keys_d" "0" +grib_check_key_equals $temp "-y -p $keys_d" "0" -#grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=s" "0s" -#grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=m" "0m" -#grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=h" "0" -#grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=s" "0s" -#grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=m" "0m" -#grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=h" "0" -#grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=s" "0" -#grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=m" "0" -#grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=h" "0" -#grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=s" "0" -#grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=m" "0" -#grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=h" "0" +grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=s" "0" +grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=m" "0" +grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=h" "0" +grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=s" "0s" +grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=m" "0m" +grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=h" "0" +grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=s" "0" +grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=m" "0" +grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=h" "0" +grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=s" "0" +grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=m" "0" +grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=h" "0" ${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp @@ -250,10 +345,10 @@ grib_check_key_equals $temp "-p $keys__" "18-24 18 24" grib_check_key_equals $temp "-y -p $keys__" "18-24 18 24" grib_check_key_equals $temp "-p $keys_s" "18-24 18 24" grib_check_key_equals $temp "-y -p $keys_s" "18-24 18 24" -grib_check_key_equals $temp "-p $keys_i" "24 18 24" # TODO(EB): Check if output of stepRange:i makes sense. -grib_check_key_equals $temp "-y -p $keys_i" "24 18 24" -grib_check_key_equals $temp "-p $keys_d" "24 18 24" # TODO(EB): Check if output of stepRange:d makes sense. -grib_check_key_equals $temp "-y -p $keys_d" "24 18 24" +grib_check_key_equals $temp "-p $keys_i" "24 18 24" +grib_check_key_equals $temp "-y -p $keys_i" "24 18 24" # TODO(EB): Check if output of stepRange:i makes sense. +grib_check_key_equals $temp "-p $keys_d" "24 18 24" +grib_check_key_equals $temp "-y -p $keys_d" "24 18 24" # TODO(EB): Check if output of stepRange:d makes sense. ${tools_dir}/grib_set -s forecastTime=1080,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=6,indicatorOfUnitForTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "1080 m 6 h" diff --git a/tests/grib_step.sh b/tests/grib_step.sh index 7a79a6e6b..037060659 100755 --- a/tests/grib_step.sh +++ b/tests/grib_step.sh @@ -137,8 +137,9 @@ grib_check_key_equals $temp "stepRange:d" "28" ${tools_dir}/grib_set -s stepRange:i=24 $grib2_sample $temp grib_check_key_equals $temp "stepRange,startStep,endStep" "24 24 24" # Should this be an error? currently this gets cast from double to int -${tools_dir}/grib_set -s stepRange:d=14.56 $grib2_sample $temp -grib_check_key_equals $temp "stepRange,startStep,endStep" "14 14 14" +# In ECC-1620 this behaviour changes +#${tools_dir}/grib_set -s stepRange:d=14.56 $grib2_sample $temp +#grib_check_key_equals $temp "stepRange,startStep,endStep" "14 14 14" # Clean up