From 123c1fda770a39c069ff87a0c33cfc960329dc01 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Tue, 11 Jul 2023 11:29:52 +0000 Subject: [PATCH 001/125] ECC-1620: Show human readable step in grid_ls --- src/CMakeLists.txt | 2 + src/grib_accessor_class_g2step_range.cc | 31 ++++- ...grib_accessor_class_step_human_readable.cc | 17 +-- src/step_optimizer.cc | 121 ++++++++++++++++++ src/step_optimizer.h | 42 ++++++ 5 files changed, 199 insertions(+), 14 deletions(-) create mode 100644 src/step_optimizer.cc create mode 100644 src/step_optimizer.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 332118567..b0b0b5236 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,8 @@ # nor does it submit to any jurisdiction. # list( APPEND eccodes_src_files + step_optimizer.cc + timer.cc grib_api.h eccodes.h action.cc diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 8d3440230..11ec414ef 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -13,6 +13,7 @@ *******************************************/ #include "grib_api_internal.h" +#include "step_optimizer.h" /* This is used by make_class.pl @@ -139,23 +140,47 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) size_t size = 0; long start = 0, theEnd = 0; + //0 m Minute + //1 h Hour + //2 D Day + //3 M Month + //4 Y Year + //5 10Y Decade + //6 30Y Normal (30 years) + //7 C Century + //10 3h 3 hours + //11 6h 6 hours + //12 12h 12 hours + //13 15m 15 minutes + //14 30m 30 minutes + //254 s Second + + ret = grib_get_long_internal(h, self->startStep, &start); + long indicatorOfUnitOfTimeRange; + ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &indicatorOfUnitOfTimeRange); + + Step startOptimizer{(int) start, indicatorOfUnitOfTimeRange}; + startOptimizer.optimizeUnit(); + if (ret) return ret; if (self->endStep == NULL) { - snprintf(buf, sizeof(buf), "%ld", start); + snprintf(buf, sizeof(buf), "%d%s", startOptimizer.value(), startOptimizer.unit_str()); } else { ret = grib_get_long_internal(h, self->endStep, &theEnd); + Step endOptimizer{(int) theEnd, indicatorOfUnitOfTimeRange}; if (ret) return ret; if (start == theEnd) { - snprintf(buf, sizeof(buf), "%ld", theEnd); + snprintf(buf, sizeof(buf), "%d%s", endOptimizer.value(), endOptimizer.unit_str()); } else { - snprintf(buf, sizeof(buf), "%ld-%ld", start, theEnd); + auto [s, e] = findCommonUnits(startOptimizer, endOptimizer); + snprintf(buf, sizeof(buf), "%d-%d%s", s.value(), e.value(), e.unit_str()); } } diff --git a/src/grib_accessor_class_step_human_readable.cc b/src/grib_accessor_class_step_human_readable.cc index 1e62e044d..70dca5fee 100644 --- a/src/grib_accessor_class_step_human_readable.cc +++ b/src/grib_accessor_class_step_human_readable.cc @@ -9,6 +9,7 @@ */ #include "grib_api_internal.h" +#include "step_optimizer.h" /* This is used by make_class.pl @@ -122,7 +123,7 @@ static int get_step_human_readable(grib_handle* h, char* result, size_t* length) { int err = 0; size_t slen = 2; - long step, hour, minute, second; + long step; /* Change units to seconds (highest resolution) * before computing the step value @@ -132,17 +133,11 @@ static int get_step_human_readable(grib_handle* h, char* result, size_t* length) err = grib_get_long(h, "step", &step); if (err) return err; - hour = step/3600; - minute = step/60 % 60; - second = step % 60; - /* sprintf(result, "%ld:%ld:%ld", hour, minute, second); */ + long indicator = grib_get_long(h, "indicatorOfUnitOfTimeRange", &indicator); + auto stepOptimizer = Step(step, indicator); + stepOptimizer.optimizeUnit(); - if (second) { - snprintf(result, 1024, "%ldh %ldm %lds", hour, minute, second); - } else { - if (minute) snprintf(result, 1024, "%ldh %ldm", hour, minute); - else snprintf(result, 1024, "%ldh", hour); - } + snprintf(result, 1024, "%d%s", stepOptimizer.value(), stepOptimizer.unit_str()); *length = strlen(result); return GRIB_SUCCESS; diff --git a/src/step_optimizer.cc b/src/step_optimizer.cc new file mode 100644 index 000000000..646459318 --- /dev/null +++ b/src/step_optimizer.cc @@ -0,0 +1,121 @@ +#include +#include +#include +#include + +#include "step_optimizer.h" + +char* Step::unit_str() const { + static char seconds[] = "s"; + static char minutes[] = "m"; + static char hours[] = "h"; + static char days[] = "d"; + switch (unit_) { + case Unit::SECOND: + return seconds; + case Unit::MINUTE: + return minutes; + case Unit::HOUR: + return hours; + case Unit::DAY: + return days; + default: + std::string msg = "Unknown unit: " + std::to_string(static_cast(unit_)); + throw std::runtime_error(msg); + } +} + +Step::Step(int value, long indicatorOfUnitOfTimeRange) { + 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."); + } + + Unit u = Unit::UNKNOWN; + switch (indicatorOfUnitOfTimeRange) { + case 0: + u = Unit::MINUTE; + break; + case 1: + u = Unit::HOUR; + break; + case 2: + u = Unit::DAY; + break; + case 254: + u = Unit::SECOND; + break; + default: + std::string msg = "Unknown indicatorOfUnitOfTimeRange: " + std::to_string(indicatorOfUnitOfTimeRange); + throw std::runtime_error(msg); + } + value_ = value; + unit_ = u; +} + +Step& Step::optimizeUnit() { + if (value_ == 0) { + return *this; + } + std::map::iterator it = unitMap_.find(unit_); + ++it; + for (; it != unitMap_.end(); ++it){ + Unit u = it->first; + int multiplier = it->second; + if (value_ % multiplier == 0) { + value_ /= multiplier; + unit_ = u; + } + else { + break; + } + } + return *this; +} + +Step& Step::setUnit(Unit new_unit) { + if (unit_ == new_unit) { + return *this; + } + std::map::iterator it = unitMap_.find(unit_); + if (new_unit > unit_) { + ++it; + for (; it != unitMap_.find(new_unit); ++it) { + int multiplier = it->second; + if (value_ % multiplier == 0) { + throw std::exception(); + } + value_ /= multiplier; + unit_ = it->first; + } + } + else { + int multiplier = it->second; + for (; it != unitMap_.find(new_unit);) { + value_ *= multiplier; + --it; + unit_ = it->first; + multiplier = it->second; + } + } + return *this; +} + +bool Step::operator==(const Step& other) const { + if (value_ == other.value_ && unit_ == other.unit_) { + return true; + } + return false; +} + +std::pair findCommonUnits(Step startStep, Step endStep) { + if (startStep.value_ == 0 || endStep.value_ == 0) { + return {startStep, endStep}; + } + + Unit unit = std::min(startStep.optimizeUnit().unit_, endStep.optimizeUnit().unit_); + startStep.setUnit(unit); + endStep.setUnit(unit); + + return {startStep, endStep}; +} diff --git a/src/step_optimizer.h b/src/step_optimizer.h new file mode 100644 index 000000000..b90fad1b5 --- /dev/null +++ b/src/step_optimizer.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include +#include +#include + +enum class Unit { + SECOND, + MINUTE, + HOUR, + DAY, + UNKNOWN +}; + +class Step { +public: + Step() : value_(0), unit_(Unit::SECOND) {} + Step(int value, long indicatorOfUnitOfTimeRange); + + int value() const { return value_; } + Unit unit() const { return unit_; } + char* unit_str() const; + + Step& optimizeUnit(); + Step& setUnit(Unit new_unit); + bool operator==(const Step& other) const; + friend std::pair findCommonUnits(Step startStep, Step endStep); + +private: + std::map unitMap_ = { + {Unit::SECOND, 0}, + {Unit::MINUTE, 60}, + {Unit::HOUR, 60}, + {Unit::DAY, 24} + }; + int value_; + Unit unit_; +}; + +std::pair findCommonUnits(Step, Step); From dbf322805e03ee5d52344c30925619c7e3b74405 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Tue, 11 Jul 2023 11:35:16 +0000 Subject: [PATCH 002/125] ECC-1620: Don't set steps to seconds --- src/grib_accessor_class_step_human_readable.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/grib_accessor_class_step_human_readable.cc b/src/grib_accessor_class_step_human_readable.cc index 70dca5fee..24c7ac823 100644 --- a/src/grib_accessor_class_step_human_readable.cc +++ b/src/grib_accessor_class_step_human_readable.cc @@ -128,8 +128,8 @@ static int get_step_human_readable(grib_handle* h, char* result, size_t* length) /* Change units to seconds (highest resolution) * before computing the step value */ - err = grib_set_string(h, "stepUnits", "s", &slen); - if (err) return err; + //err = grib_set_string(h, "stepUnits", "s", &slen); + //if (err) return err; err = grib_get_long(h, "step", &step); if (err) return err; From f0e207386911635108d639f606b5dd74b5ae6a44 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Tue, 11 Jul 2023 11:50:28 +0000 Subject: [PATCH 003/125] ECC-1620: Remove timer.cc from CMakeLists.txt --- src/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b0b0b5236..8a3cf1ed0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,6 @@ # list( APPEND eccodes_src_files step_optimizer.cc - timer.cc grib_api.h eccodes.h action.cc @@ -264,7 +263,6 @@ list( APPEND eccodes_src_files grib_accessor_class_abstract_long_vector.cc grib_loader_from_handle.cc grib_bits.cc - grib_timer.cc grib_ibmfloat.cc grib_ieeefloat.cc grib_accessor_class_reference_value_error.cc From 0a5cca89c8fe97f87da735f0cf0b2d925ba1495d Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Tue, 11 Jul 2023 13:23:32 +0000 Subject: [PATCH 004/125] ECC-1620: Consider different units --- src/CMakeLists.txt | 1 + src/grib_accessor_class_g2step_range.cc | 24 +++++++++++++++++++++--- src/step_optimizer.cc | 15 +++++++++++++++ src/step_optimizer.h | 2 ++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a3cf1ed0..2adbef70a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ list( APPEND eccodes_src_files step_optimizer.cc grib_api.h + grib_timer.cc eccodes.h action.cc action_class_alias.cc diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 11ec414ef..6576d3de0 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -157,10 +157,19 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) ret = grib_get_long_internal(h, self->startStep, &start); + if (ret) + return ret; long indicatorOfUnitOfTimeRange; + long forecastTime; ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &indicatorOfUnitOfTimeRange); + if (ret) + return ret; + ret = grib_get_long_internal(h, "forecastTime", &forecastTime); + if (ret) + return ret; - Step startOptimizer{(int) start, indicatorOfUnitOfTimeRange}; + + Step startOptimizer{(int) forecastTime, indicatorOfUnitOfTimeRange}; startOptimizer.optimizeUnit(); if (ret) @@ -170,8 +179,17 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) snprintf(buf, sizeof(buf), "%d%s", startOptimizer.value(), startOptimizer.unit_str()); } else { - ret = grib_get_long_internal(h, self->endStep, &theEnd); - Step endOptimizer{(int) theEnd, indicatorOfUnitOfTimeRange}; + long indicatorOfUnitForTimeRange; + long lengthOfTimeRange; + ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &indicatorOfUnitForTimeRange); + if (ret) + return ret; + ret = grib_get_long_internal(h, "lengthOfTimeRange", &lengthOfTimeRange); + if (ret) + return ret; + //ret = grib_get_long_internal(h, self->endStep, &theEnd); + Step length{(int) lengthOfTimeRange, indicatorOfUnitForTimeRange}; + Step endOptimizer = startOptimizer + length; if (ret) return ret; diff --git a/src/step_optimizer.cc b/src/step_optimizer.cc index 646459318..e98aed2fc 100644 --- a/src/step_optimizer.cc +++ b/src/step_optimizer.cc @@ -53,6 +53,15 @@ Step::Step(int value, long indicatorOfUnitOfTimeRange) { unit_ = u; } +Step::Step(int value, Unit 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; +} + Step& Step::optimizeUnit() { if (value_ == 0) { return *this; @@ -108,6 +117,12 @@ bool Step::operator==(const Step& other) const { return false; } +Step operator+(const Step step1, const Step step2) { + auto [a, b] = findCommonUnits(step1, step2); + return Step(a.value_ + b.value_, a.unit_); +} + + std::pair findCommonUnits(Step startStep, Step endStep) { if (startStep.value_ == 0 || endStep.value_ == 0) { return {startStep, endStep}; diff --git a/src/step_optimizer.h b/src/step_optimizer.h index b90fad1b5..913fc30de 100644 --- a/src/step_optimizer.h +++ b/src/step_optimizer.h @@ -18,6 +18,7 @@ class Step { public: Step() : value_(0), unit_(Unit::SECOND) {} Step(int value, long indicatorOfUnitOfTimeRange); + Step(int value, Unit unit); int value() const { return value_; } Unit unit() const { return unit_; } @@ -27,6 +28,7 @@ public: Step& setUnit(Unit new_unit); bool operator==(const Step& other) const; friend std::pair findCommonUnits(Step startStep, Step endStep); + friend Step operator+(const Step step1, const Step step2); private: std::map unitMap_ = { From 3a9172e3f4f8b8098a0338f4a8055c63b6d4250d Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Tue, 11 Jul 2023 13:35:11 +0000 Subject: [PATCH 005/125] ECC-1620: Minor fixes --- src/grib_accessor_class_g2step_range.cc | 27 ++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 6576d3de0..cf71eb1bf 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -138,7 +138,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) char buf[100]; int ret = 0; size_t size = 0; - long start = 0, theEnd = 0; + //long start = 0, theEnd = 0; //0 m Minute //1 h Hour @@ -156,7 +156,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) //254 s Second - ret = grib_get_long_internal(h, self->startStep, &start); + //ret = grib_get_long_internal(h, self->startStep, &start); if (ret) return ret; long indicatorOfUnitOfTimeRange; @@ -169,14 +169,14 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; - Step startOptimizer{(int) forecastTime, indicatorOfUnitOfTimeRange}; - startOptimizer.optimizeUnit(); + Step step_a{(int) forecastTime, indicatorOfUnitOfTimeRange}; + step_a.optimizeUnit(); if (ret) return ret; if (self->endStep == NULL) { - snprintf(buf, sizeof(buf), "%d%s", startOptimizer.value(), startOptimizer.unit_str()); + snprintf(buf, sizeof(buf), "%d%s", step_a.value(), step_a.unit_str()); } else { long indicatorOfUnitForTimeRange; @@ -185,20 +185,19 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) if (ret) return ret; ret = grib_get_long_internal(h, "lengthOfTimeRange", &lengthOfTimeRange); - if (ret) - return ret; - //ret = grib_get_long_internal(h, self->endStep, &theEnd); - Step length{(int) lengthOfTimeRange, indicatorOfUnitForTimeRange}; - Step endOptimizer = startOptimizer + length; if (ret) return ret; - if (start == theEnd) { - snprintf(buf, sizeof(buf), "%d%s", endOptimizer.value(), endOptimizer.unit_str()); + Step length{(int) lengthOfTimeRange, indicatorOfUnitForTimeRange}; + Step step_b = step_a + length; + step_b.optimizeUnit(); + auto [a, b] = findCommonUnits(step_a, step_b); + + if (a.value() == 0) { + snprintf(buf, sizeof(buf), "%d%s", step_b.value(), step_b.unit_str()); } else { - auto [s, e] = findCommonUnits(startOptimizer, endOptimizer); - snprintf(buf, sizeof(buf), "%d-%d%s", s.value(), e.value(), e.unit_str()); + snprintf(buf, sizeof(buf), "%d-%d%s", a.value(), b.value(), a.unit_str()); } } From 140b7d84c6880334e05c7cdbf2c174186dbb0f68 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Tue, 11 Jul 2023 13:40:09 +0000 Subject: [PATCH 006/125] ECC-1620: Show range instead of starting point --- src/grib_accessor_class_g2step_range.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index cf71eb1bf..7eb25c0cc 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -193,12 +193,12 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) step_b.optimizeUnit(); auto [a, b] = findCommonUnits(step_a, step_b); - if (a.value() == 0) { - snprintf(buf, sizeof(buf), "%d%s", step_b.value(), step_b.unit_str()); - } - else { + //if (a.value() == 0) { + // snprintf(buf, sizeof(buf), "%d%s", step_b.value(), step_b.unit_str()); + //} + //else { snprintf(buf, sizeof(buf), "%d-%d%s", a.value(), b.value(), a.unit_str()); - } + //} } size = strlen(buf) + 1; From bfe9d6344961cf6261a1659f11aa7af57e2b1aa6 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Tue, 11 Jul 2023 13:44:14 +0000 Subject: [PATCH 007/125] ECC-1620: Fix unit --- src/grib_accessor_class_g2step_range.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 7eb25c0cc..5228163fe 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -193,12 +193,12 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) step_b.optimizeUnit(); auto [a, b] = findCommonUnits(step_a, step_b); - //if (a.value() == 0) { - // snprintf(buf, sizeof(buf), "%d%s", step_b.value(), step_b.unit_str()); - //} - //else { + if (a.value() == 0) { + snprintf(buf, sizeof(buf), "0-%d%s", step_b.value(), step_b.unit_str()); + } + else { snprintf(buf, sizeof(buf), "%d-%d%s", a.value(), b.value(), a.unit_str()); - //} + } } size = strlen(buf) + 1; From c354ff248aafa846184a49577badd22a437a31c2 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 12 Jul 2023 10:31:59 +0000 Subject: [PATCH 008/125] ECC-1620: Fix unit, when range starts from 0 --- src/step_optimizer.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/step_optimizer.cc b/src/step_optimizer.cc index e98aed2fc..5ea2c6ced 100644 --- a/src/step_optimizer.cc +++ b/src/step_optimizer.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include "step_optimizer.h" @@ -83,6 +84,10 @@ Step& Step::optimizeUnit() { } Step& Step::setUnit(Unit new_unit) { + if (value_ == 0) { + unit_ = new_unit; + return *this; + } if (unit_ == new_unit) { return *this; } @@ -125,6 +130,17 @@ Step operator+(const Step step1, const Step step2) { std::pair findCommonUnits(Step startStep, Step endStep) { if (startStep.value_ == 0 || endStep.value_ == 0) { + if (startStep.value_ == 0 && endStep.value_ == 0) { + Unit unit = std::max(startStep.unit_, endStep.unit_); + startStep.setUnit(unit); + endStep.setUnit(unit); + } + else if (startStep.value_ == 0) { + startStep.setUnit(endStep.unit_); + } + else if (endStep.value_ == 0) { + endStep.setUnit(startStep.unit_); + } return {startStep, endStep}; } From 1517f9604f6fd818c66b829fa914c5b4f82d4a0d Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 10 Aug 2023 08:42:44 +0000 Subject: [PATCH 009/125] nai --- definitions/grib2/boot.def | 1 + .../grib2/template.4.forecast_time.def | 5 +- src/grib_accessor_class_g2end_step.cc | 364 ++++++++++++------ src/grib_accessor_class_g2step_range.cc | 125 ++++-- ...grib_accessor_class_step_human_readable.cc | 2 +- src/grib_accessor_class_step_in_units.cc | 214 +++++++--- src/step_optimizer.cc | 247 ++++++++---- src/step_optimizer.h | 190 ++++++++- tools/grib_ls.cc | 1 + tools/grib_options.cc | 5 + tools/grib_tools.cc | 21 +- tools/grib_tools.h | 2 + 12 files changed, 903 insertions(+), 274 deletions(-) diff --git a/definitions/grib2/boot.def b/definitions/grib2/boot.def index 32f262bef..cd90c57d1 100644 --- a/definitions/grib2/boot.def +++ b/definitions/grib2/boot.def @@ -17,6 +17,7 @@ constant million = 1000000 : hidden; constant grib2divider = 1000000; alias extraDimensionPresent=zero; transient angleSubdivisions=grib2divider; # micro degrees +transient stepOutputFormat=""; meta gts_header gts_header() : no_copy,hidden,read_only; meta gts_TTAAii gts_header(20,6) : no_copy,hidden,read_only; diff --git a/definitions/grib2/template.4.forecast_time.def b/definitions/grib2/template.4.forecast_time.def index 662310fc6..1f31f48c7 100644 --- a/definitions/grib2/template.4.forecast_time.def +++ b/definitions/grib2/template.4.forecast_time.def @@ -10,9 +10,10 @@ 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 +;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; +;codetable[1] stepUnits 'stepUnits.table' = defaultStepUnits : transient,dump,no_copy; +codetable[1] stepUnits 'stepUnits.table' = 255: transient,dump,no_copy; # Forecast time in units defined by previous octet (GRIB-29: supports negative forecast time) signed[4] forecastTime : dump; diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 285a30085..1388cdeed 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -9,6 +9,9 @@ */ #include "grib_api_internal.h" +#include "step_optimizer.h" +#include + /* This is used by make_class.pl @@ -55,6 +58,10 @@ 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 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 void dump(grib_accessor*, grib_dumper*); static void init(grib_accessor*, const long, grib_arguments*); @@ -107,12 +114,12 @@ 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 */ 0, /* pack_float */ - 0, /* unpack_double */ + &unpack_double, /* unpack_double */ 0, /* unpack_float */ - 0, /* pack_string */ - 0, /* unpack_string */ + &pack_string, /* pack_string */ + &unpack_string, /* unpack_string */ 0, /* pack_string_array */ 0, /* unpack_string_array */ 0, /* pack_bytes */ @@ -233,27 +240,36 @@ static int convert_time_range( Assert(lengthOfTimeRange != NULL); if (indicatorOfUnitForTimeRange != 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; + Step step{(int) *lengthOfTimeRange, indicatorOfUnitForTimeRange}; + if (stepUnits != 255) { + step.setUnit(stepUnits); } else { - u2sf_step_unit = u2s[stepUnits]; + step.setUnit(indicatorOfUnitForTimeRange); } - 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; + *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; } return GRIB_SUCCESS; @@ -391,109 +407,237 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) } } +// 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); + grib_handle* h = grib_handle_of_accessor(a); + int ret = 0; - int err = 0; + Step step{(int) *val, StepUnitsTable::to_long("h")}; + ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit_as_long()); + if (ret) + return ret; - long year; - long month; - long day; - long hour; - long minute; - long second; + ret = grib_set_long_internal(h, "lengthOfTimeRange", step.value()); + if (ret) + return ret; + return GRIB_SUCCESS; - 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; - long coded_time_range, time_range, typeOfTimeIncrement; +// grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; +// grib_handle* h = grib_handle_of_accessor(a); - double dend, dstep; +// int err = 0; - /*point in time */ - if (self->year == NULL) { - err = grib_set_long_internal(h, self->start_step, *val); - return err; +// long year; +// long month; +// long day; +// long hour; +// long minute; +// long second; + +// 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; + +// 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; +} + +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 step = Step(parse_step(std::string(val))); + + ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit_as_long()); + if (ret) + return ret; + + ret = grib_set_long_internal(h, "lengthOfTimeRange", step.value()); + if (ret) + return ret; + + return GRIB_SUCCESS; +} + + +//static int unpack_string(grib_accessor* a, char* val, size_t* len) { +// throw std::runtime_error("g2end_step: unpack_string() is not implemented"); +// //return GRIB_NOT_IMPLEMENTED; +//} + +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; + + long unit; + ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit); + if (ret) + return ret; + + long value; + ret = grib_get_long_internal(h, "lengthOfTimeRange", &value); + if (ret) + return ret; + + Step step{(int) value, unit}; + + sprintf(val, "%d%s", step.value(), step.unit_as_str().c_str()); + + 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 unit; + ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit); + if (ret) + return ret; + + + long stepUnits; + ret = grib_get_long_internal(h, "stepUnits", &stepUnits); + if (ret) + return ret; + + Step step; + if (stepUnits != 255) { + step = Step((int) *val, stepUnits); + } + else { + step = Step((int) *val, unit); } - 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; + ret = grib_set_long_internal(h, "lengthOfTimeRange", step.value()); + if (ret) + return ret; + ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit_as_long()); + if (ret) + return ret; - 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; + return ret; +} - time_range = *val - start_step; +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; - if (time_range < 0) { - grib_context_log(h->context, GRIB_LOG_ERROR, - "endStep < startStep (%ld < %ld)", *val, start_step); - return GRIB_WRONG_STEP; + long unit; + ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit); + if (ret) + 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; + + if (stepUnits != 255) { + Step step = Step(value, unit); + *val = step.getDoubleValue(stepUnits); } - - 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; + else { + Step step = Step(value, unit); + *val = step.value(); } return GRIB_SUCCESS; diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 5228163fe..8c8a35b23 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_optimizer.h" +#include /* This is used by make_class.pl @@ -140,22 +141,6 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) size_t size = 0; //long start = 0, theEnd = 0; - //0 m Minute - //1 h Hour - //2 D Day - //3 M Month - //4 Y Year - //5 10Y Decade - //6 30Y Normal (30 years) - //7 C Century - //10 3h 3 hours - //11 6h 6 hours - //12 12h 12 hours - //13 15m 15 minutes - //14 30m 30 minutes - //254 s Second - - //ret = grib_get_long_internal(h, self->startStep, &start); if (ret) return ret; @@ -169,14 +154,29 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; + size_t stepUnitsSize = 128; + char stepUnits[stepUnitsSize]; + ret = grib_get_string_internal(h, "stepUnits", stepUnits, &stepUnitsSize); + if (ret) + return ret; + //printf("stepUnits=%s\n", stepUnits); + + size_t stepOutputFormatSize = 128; + char stepOutputFormat[stepOutputFormatSize]; + ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize); + if (ret) + return ret; + //printf("stepOutputFormat=%s\n", stepOutputFormat); + Step step_a{(int) forecastTime, indicatorOfUnitOfTimeRange}; step_a.optimizeUnit(); - if (ret) - return ret; + if (strcmp(stepOutputFormat, "future") != 0) { + step_a.hide_hour_unit(); + } if (self->endStep == NULL) { - snprintf(buf, sizeof(buf), "%d%s", step_a.value(), step_a.unit_str()); + snprintf(buf, sizeof(buf), "%d%s", step_a.value(), step_a.unit_as_str().c_str()); } else { long indicatorOfUnitForTimeRange; @@ -193,11 +193,16 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) step_b.optimizeUnit(); auto [a, b] = findCommonUnits(step_a, step_b); + if (strcmp(stepOutputFormat, "future") != 0) { + step_b.hide_hour_unit(); + a.hide_hour_unit(); + b.hide_hour_unit(); + } if (a.value() == 0) { - snprintf(buf, sizeof(buf), "0-%d%s", step_b.value(), step_b.unit_str()); + snprintf(buf, sizeof(buf), "0-%d%s", step_b.value(), step_b.unit_as_str().c_str()); } else { - snprintf(buf, sizeof(buf), "%d-%d%s", a.value(), b.value(), a.unit_str()); + snprintf(buf, sizeof(buf), "%d-%d%s", a.value(), b.value(), step_b.unit_as_str().c_str()); } } @@ -213,29 +218,83 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return GRIB_SUCCESS; } + static int pack_string(grib_accessor* a, const char* val, size_t* len) { grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; grib_handle* h = grib_handle_of_accessor(a); - - long start = 0, theEnd = -1; int ret = 0; - char *p = NULL, *q = NULL; - start = strtol(val, &p, 10); - theEnd = start; + std::vector steps = parse_range(val); + if (steps.size() == 0) { + return GRIB_INVALID_ARGUMENT; + } + //ret = grib_set_long_internal(h, self->startStep, steps[0].value()); + //if (ret) + // return ret; - if (*p != 0) - theEnd = strtol(++p, &q, 10); - ret = grib_set_long_internal(h, self->startStep, start); - if (ret) - return ret; + //printf("val: %s\n", val); - if (self->endStep != NULL) { - ret = grib_set_long_internal(h, self->endStep, theEnd); + if (steps.size() == 1) { + //printf("unit_str 1: %s\n", steps[0].unit_as_str().c_str()); + steps[0].optimizeUnit(); + ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", steps[0].unit_as_long()); + if (ret) + return ret; + + ret = grib_set_long_internal(h, "forecastTime", steps[0].value()); if (ret) return ret; } + else if (steps.size() == 2) { + //ret = grib_set_long_internal(h, self->endStep, steps[1].value()); + //if (ret) + // return ret; + //printf("unit_str 2: %s\n", steps[1].unit_as_str().c_str()); + + steps[0].optimizeUnit(); + steps[1].optimizeUnit(); + auto [a, b] = findCommonUnits(steps[0], steps[1]); + + ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", a.unit_as_long()); + if (ret) + return ret; + ret = grib_set_long_internal(h, "forecastTime", a.value()); + if (ret) + return ret; + + + ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", b.unit_as_long()); + if (ret) + return ret; + ret = grib_set_long_internal(h, "lengthOfTimeRange", b.value()); + if (ret) + return ret; + } + else { + std::string msg = std::string("Invalid range: ") + val; + throw std::runtime_error(msg); + } + + + //long start = 0, theEnd = -1; + //int ret = 0; + //char *p = NULL, *q = NULL; + + //start = strtol(val, &p, 10); + //theEnd = start; + + //if (*p != 0) + // theEnd = strtol(++p, &q, 10); + //ret = grib_set_long_internal(h, self->startStep, start); + //if (ret) + // return ret; + + //if (self->endStep != NULL) { + // ret = grib_set_long_internal(h, self->endStep, theEnd); + // if (ret) + // return ret; + //} return 0; } diff --git a/src/grib_accessor_class_step_human_readable.cc b/src/grib_accessor_class_step_human_readable.cc index 24c7ac823..d9fe32d25 100644 --- a/src/grib_accessor_class_step_human_readable.cc +++ b/src/grib_accessor_class_step_human_readable.cc @@ -137,7 +137,7 @@ static int get_step_human_readable(grib_handle* h, char* result, size_t* length) auto stepOptimizer = Step(step, indicator); stepOptimizer.optimizeUnit(); - snprintf(result, 1024, "%d%s", stepOptimizer.value(), stepOptimizer.unit_str()); + snprintf(result, 1024, "%d%s", stepOptimizer.value(), stepOptimizer.unit_as_str().c_str()); *length = strlen(result); return GRIB_SUCCESS; diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index acf570c19..99d493bd5 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -9,6 +9,8 @@ */ #include "grib_api_internal.h" +#include "step_optimizer.h" +#include /* This is used by make_class.pl @@ -39,6 +41,10 @@ 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 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 void dump(grib_accessor*, grib_dumper*); static void init(grib_accessor*, const long, grib_arguments*); @@ -78,12 +84,12 @@ 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 */ 0, /* pack_float */ - 0, /* unpack_double */ + &unpack_double, /* unpack_double */ 0, /* unpack_float */ - 0, /* pack_string */ - 0, /* unpack_string */ + &pack_string, /* pack_string */ + &unpack_string, /* unpack_string */ 0, /* pack_string_array */ 0, /* unpack_string_array */ 0, /* pack_bytes */ @@ -214,52 +220,172 @@ 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 err = 0; - long codedStep, codedUnits, stepUnits; - long oldStep = 0; - long indicatorOfUnitForTimeRange, lengthOfTimeRange; + grib_handle* h = grib_handle_of_accessor(a); + int ret = 0; - if ((err = grib_get_long_internal(h, self->codedUnits, &codedUnits))) - return err; - if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits))) - return err; + Step step{(int) *val, StepUnitsTable::to_long("h")}; + ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", step.unit_as_long()); + if (ret) + return ret; - unpack_long(a, &oldStep, len); + ret = grib_set_long_internal(h, "forecastTime", step.value()); + if (ret) + return ret; + return GRIB_SUCCESS; - if (stepUnits != codedUnits) { - codedStep = *val * u2s[stepUnits]; - if (codedStep % u2s2[codedUnits] != 0) { - codedUnits = stepUnits; - err = grib_set_long_internal(h, self->codedUnits, codedUnits); - if (err != GRIB_SUCCESS) - return err; - codedStep = *val; - } - else { - codedStep = codedStep / u2s2[codedUnits]; - } + //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; + //long indicatorOfUnitForTimeRange, lengthOfTimeRange; + + //if ((err = grib_get_long_internal(h, self->codedUnits, &codedUnits))) + // return err; + //if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits))) + // return err; + + //unpack_long(a, &oldStep, len); + + //if (stepUnits != codedUnits) { + // codedStep = *val * u2s[stepUnits]; + // if (codedStep % u2s2[codedUnits] != 0) { + // codedUnits = stepUnits; + // err = grib_set_long_internal(h, self->codedUnits, codedUnits); + // if (err != GRIB_SUCCESS) + // return err; + // codedStep = *val; + // } + // else { + // codedStep = codedStep / u2s2[codedUnits]; + // } + //} + //else { + // codedStep = *val; + //} + + //if (self->indicatorOfUnitForTimeRange) { + // if ((err = grib_get_long_internal(h, + // self->indicatorOfUnitForTimeRange, &indicatorOfUnitForTimeRange))) + // return err; + // if ((err = grib_get_long_internal(h, + // self->lengthOfTimeRange, &lengthOfTimeRange))) + // return err; + // if (codedUnits == indicatorOfUnitForTimeRange) + // lengthOfTimeRange -= codedStep - oldStep; + // else + // lengthOfTimeRange -= codedStep * u2s2[codedUnits] / u2s2[indicatorOfUnitForTimeRange]; + // lengthOfTimeRange = lengthOfTimeRange > 0 ? lengthOfTimeRange : 0; + // err = grib_set_long_internal(grib_handle_of_accessor(a), self->lengthOfTimeRange, lengthOfTimeRange); + // if (err != GRIB_SUCCESS) + // return err; + //} + + //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) { + 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, "indicatorOfUnitOfTimeRange", step.unit_as_long()); + if (ret) + return ret; + + ret = grib_set_long_internal(h, "forecastTime", step.value()); + if (ret) + return ret; + + return GRIB_SUCCESS; +} + +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; + + long unit; + ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &unit); + if (ret) + return ret; + + long value; + ret = grib_get_long_internal(h, "forecastTime", &value); + if (ret) + return ret; + + Step step{(int) value, unit}; + sprintf(val, "%d%s", step.value(), step.unit_as_str().c_str()); + + return GRIB_SUCCESS; +} + + +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, "indicatorOfUnitOfTimeRange", &unit); + if (ret) + return ret; + + + long stepUnits; + ret = grib_get_long_internal(h, self->stepUnits, &stepUnits); + if (ret) + return ret; + + Step step; + if (stepUnits != 255) { + step = Step((int) *val, stepUnits); } else { - codedStep = *val; + step = Step((int) *val, unit); } - if (self->indicatorOfUnitForTimeRange) { - if ((err = grib_get_long_internal(h, - self->indicatorOfUnitForTimeRange, &indicatorOfUnitForTimeRange))) - return err; - if ((err = grib_get_long_internal(h, - self->lengthOfTimeRange, &lengthOfTimeRange))) - return err; - if (codedUnits == indicatorOfUnitForTimeRange) - lengthOfTimeRange -= codedStep - oldStep; - else - lengthOfTimeRange -= codedStep * u2s2[codedUnits] / u2s2[indicatorOfUnitForTimeRange]; - lengthOfTimeRange = lengthOfTimeRange > 0 ? lengthOfTimeRange : 0; - err = grib_set_long_internal(grib_handle_of_accessor(a), self->lengthOfTimeRange, lengthOfTimeRange); - if (err != GRIB_SUCCESS) - return err; - } + ret = grib_set_long_internal(h, "forecastTime", step.value()); + if (ret) + return ret; + ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", step.unit_as_long()); + if (ret) + return ret; - return grib_set_long_internal(grib_handle_of_accessor(a), self->codedStep, codedStep); + return ret; +} + + +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 = 0; + + long unit; + ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &unit); + if (ret) + return ret; + + long value; + ret = grib_get_long_internal(h, "forecastTime", &value); + if (ret) + return ret; + + long stepUnits; + ret = grib_get_long_internal(h, self->stepUnits, &stepUnits); + if (ret) + return ret; + + if (stepUnits != 255) { + Step step = Step(value, unit); + *val = step.getDoubleValue(stepUnits); + } + else { + Step step = Step(value, unit); + *val = step.value(); + } + + return GRIB_SUCCESS; } diff --git a/src/step_optimizer.cc b/src/step_optimizer.cc index 5ea2c6ced..e65611712 100644 --- a/src/step_optimizer.cc +++ b/src/step_optimizer.cc @@ -6,52 +6,65 @@ #include "step_optimizer.h" -char* Step::unit_str() const { - static char seconds[] = "s"; - static char minutes[] = "m"; - static char hours[] = "h"; - static char days[] = "d"; - switch (unit_) { - case Unit::SECOND: - return seconds; - case Unit::MINUTE: - return minutes; - case Unit::HOUR: - return hours; - case Unit::DAY: - return days; - default: - std::string msg = "Unknown unit: " + std::to_string(static_cast(unit_)); - throw std::runtime_error(msg); + +std::string parse_step(std::string step) { + if (step.find_first_of("smhdMYC") == std::string::npos) { + step += "h"; } + return step; } -Step::Step(int value, long indicatorOfUnitOfTimeRange) { + +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; +} + + +std::string Step::unit_as_str() const { + if ((unit_ == Unit::HOUR) && hide_hour_unit_) + return std::string(""); + else + return StepUnitsTable::to_str(unit_); +} + +long Step::unit_as_long() const { + return unit_; +} + +Step::Step(int value, long 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."); } - Unit u = Unit::UNKNOWN; - switch (indicatorOfUnitOfTimeRange) { - case 0: - u = Unit::MINUTE; - break; - case 1: - u = Unit::HOUR; - break; - case 2: - u = Unit::DAY; - break; - case 254: - u = Unit::SECOND; - break; - default: - std::string msg = "Unknown indicatorOfUnitOfTimeRange: " + std::to_string(indicatorOfUnitOfTimeRange); - throw std::runtime_error(msg); - } value_ = value; - unit_ = u; + unit_ = StepUnitsTable::to_unit(unit); +} + +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_ = StepUnitsTable::to_unit(u_str); } Step::Step(int value, Unit u) { @@ -67,22 +80,51 @@ Step& Step::optimizeUnit() { if (value_ == 0) { return *this; } - std::map::iterator it = unitMap_.find(unit_); - ++it; - for (; it != unitMap_.end(); ++it){ - Unit u = it->first; - int multiplier = it->second; - if (value_ % multiplier == 0) { - value_ /= multiplier; - unit_ = u; - } - else { + + Seconds duration(0); + switch (unit_) { + 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: " + StepUnitsTable::to_str(unit_); + throw std::runtime_error(msg); + } + + for (auto it = unitMap_.end(); it != unitMap_.begin();) { + --it; + int multiplier = it->second; + if (duration.count() % multiplier == 0) { + value_ = duration.count() / multiplier; + unit_ = it->first; + return *this; } } return *this; } +Step& Step::setUnit(std::string new_unit) { + setUnit(StepUnitsTable::to_unit(new_unit)); + return *this; +} + +Step& Step::setUnit(long new_unit) { + setUnit(StepUnitsTable::to_unit(new_unit)); + return *this; +} + Step& Step::setUnit(Unit new_unit) { if (value_ == 0) { unit_ = new_unit; @@ -91,30 +133,101 @@ Step& Step::setUnit(Unit new_unit) { if (unit_ == new_unit) { return *this; } - std::map::iterator it = unitMap_.find(unit_); - if (new_unit > unit_) { - ++it; - for (; it != unitMap_.find(new_unit); ++it) { - int multiplier = it->second; - if (value_ % multiplier == 0) { - throw std::exception(); - } - value_ /= multiplier; - unit_ = it->first; - } + Seconds duration(0); + switch (unit_) { + 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: " + std::to_string(static_cast(unit_)); + throw std::runtime_error(msg); } - else { - int multiplier = it->second; - for (; it != unitMap_.find(new_unit);) { - value_ *= multiplier; - --it; - unit_ = it->first; - multiplier = it->second; - } + + switch (new_unit) { + case Unit::SECOND: + value_ = duration.count(); + break; + case Unit::MINUTE: + value_ = std::chrono::duration_cast(duration).count(); + break; + case Unit::HOUR: + value_ = std::chrono::duration_cast(duration).count(); + break; + case Unit::DAY: + value_ = std::chrono::duration_cast(duration).count(); + break; + case Unit::MONTH: + value_ = std::chrono::duration_cast(duration).count(); + break; + default: + std::string msg = "Unknown unit: " + std::to_string(static_cast(new_unit)); + throw std::runtime_error(msg); } + unit_ = new_unit; + return *this; } +double Step::getDoubleValue(long new_unit) const { + Seconds duration(0); + switch (unit_) { + 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: " + std::to_string(static_cast(unit_)); + throw std::runtime_error(msg); + } + + double value; + switch (new_unit) { + case Unit::SECOND: + value = std::chrono::duration_cast(duration).count(); + break; + case Unit::MINUTE: + value = std::chrono::duration_cast(duration).count(); + break; + case Unit::HOUR: + value = std::chrono::duration_cast(duration).count(); + break; + case Unit::DAY: + value = std::chrono::duration_cast(duration).count(); + break; + case Unit::MONTH: + value = std::chrono::duration_cast(duration).count(); + break; + default: + std::string msg = "Unknown unit: " + std::to_string(static_cast(new_unit)); + throw std::runtime_error(msg); + } + + return value; +} + bool Step::operator==(const Step& other) const { if (value_ == other.value_ && unit_ == other.unit_) { return true; @@ -131,7 +244,7 @@ Step operator+(const Step step1, const Step step2) { std::pair findCommonUnits(Step startStep, Step endStep) { if (startStep.value_ == 0 || endStep.value_ == 0) { if (startStep.value_ == 0 && endStep.value_ == 0) { - Unit unit = std::max(startStep.unit_, endStep.unit_); + Unit unit = StepUnitsTable::unit_duration(startStep.unit_) > StepUnitsTable::unit_duration(endStep.unit_) ? startStep.unit_ : endStep.unit_; startStep.setUnit(unit); endStep.setUnit(unit); } diff --git a/src/step_optimizer.h b/src/step_optimizer.h index 913fc30de..9b88fcd70 100644 --- a/src/step_optimizer.h +++ b/src/step_optimizer.h @@ -5,40 +5,200 @@ #include #include #include +#include +#include +#include -enum class Unit { - SECOND, - MINUTE, - HOUR, - DAY, - UNKNOWN + +enum Unit : long { + MINUTE = 0, + HOUR = 1, + DAY = 2, + MONTH = 3, + YEAR = 4, + YEARS10 = 5, + YEARS30 = 6, + CENTURY = 7, + HOURS3 = 10, + HOURS6 = 11, + HOURS12 = 12, + SECOND = 13, + MINUTES15 = 14, + MINUTES30 = 15, + MISSING = 255, }; +using Minutes = std::chrono::duration>; +using Hours = std::chrono::duration>; +using Days = std::chrono::duration>; +using Months = std::chrono::duration>; +using Years = std::chrono::duration>; +using Years10 = std::chrono::duration>; +using Years30 = std::chrono::duration>; +using Centuries = std::chrono::duration>; +using Hours3 = std::chrono::duration>; +using Hours6 = std::chrono::duration>; +using Hours12 = std::chrono::duration>; +using Seconds = std::chrono::duration>; +using Minutes15 = std::chrono::duration>; +using Minutes30 = std::chrono::duration>; +using Missing = std::chrono::duration>; + +using MinutesDouble = std::chrono::duration>; +using HoursDouble = std::chrono::duration>; +using DaysDouble = std::chrono::duration>; +using MonthsDouble = std::chrono::duration>; +using YearsDouble = std::chrono::duration>; +using Years10Double = std::chrono::duration>; +using Years30Double = std::chrono::duration>; +using CenturiesDouble = std::chrono::duration>; +using Hours3Double = std::chrono::duration>; +using Hours6Double = std::chrono::duration>; +using Hours12Double = std::chrono::duration>; +using SecondsDouble = std::chrono::duration>; +using Minutes15Double = std::chrono::duration>; +using Minutes30Double = std::chrono::duration>; +using MissingDouble = std::chrono::duration>; + +class StepUnitsTable{ +private: + StepUnitsTable() { + } +public: + static Unit to_unit(const std::string& str) { + static std::map map = { + {"m", Unit::MINUTE}, + {"h", Unit::HOUR}, + {"d", Unit::DAY}, + {"M", Unit::MONTH}, + {"Y", Unit::YEAR}, + {"10Y", Unit::YEARS10}, + {"30Y", Unit::YEARS30}, + {"C", Unit::CENTURY}, + {"3h", Unit::HOURS3}, + {"6h", Unit::HOURS6}, + {"12h", Unit::HOURS12}, + {"s", Unit::SECOND}, + {"15m", Unit::MINUTES15}, + {"30m", Unit::MINUTES30}, + {"255", Unit::MISSING}, + }; + return map[str]; + } + + static long to_long(const std::string& str) { + return to_unit(str); + } + + static Unit to_unit(long code) { + static std::map map = { + {Unit::MINUTE, Unit::MINUTE}, + {Unit::HOUR, Unit::HOUR}, + {Unit::DAY, Unit::DAY}, + {Unit::MONTH, Unit::MONTH}, + {Unit::YEAR, Unit::YEAR}, + {Unit::YEARS10, Unit::YEARS10}, + {Unit::YEARS30, Unit::YEARS30}, + {Unit::CENTURY, Unit::CENTURY}, + {Unit::HOURS3, Unit::HOURS3}, + {Unit::HOURS6, Unit::HOURS6}, + {Unit::HOURS12, Unit::HOURS12}, + {Unit::SECOND, Unit::SECOND}, + {Unit::MINUTES15, Unit::MINUTES15}, + {Unit::MINUTES30, Unit::MINUTES30}, + {Unit::MISSING, Unit::MISSING}, + }; + return map[code]; + } + + static std::string to_str(long code) { + static std::map map = { + {Unit::MINUTE, "m"}, + {Unit::HOUR, "h"}, + {Unit::DAY, "d"}, + {Unit::MONTH, "M"}, + {Unit::YEAR, "Y"}, + {Unit::YEARS10, "10Y"}, + {Unit::YEARS30, "30Y"}, + {Unit::CENTURY, "C"}, + {Unit::HOURS3, "3h"}, + {Unit::HOURS6, "6h"}, + {Unit::HOURS12, "12h"}, + {Unit::SECOND, "s"}, + {Unit::MINUTES15, "15m"}, + {Unit::MINUTES30, "30m"}, + {Unit::MISSING, "255"}, + }; + return map[code]; + } + + static double unit_duration(long code) { + static std::map map = { + {Unit::MINUTE, Minutes::period::num / Minutes::period::den}, + {Unit::HOUR, Hours::period::num / Hours::period::den}, + {Unit::DAY, Days::period::num / Days::period::den}, + {Unit::MONTH, Months::period::num / Months::period::den}, + {Unit::YEAR, Years::period::num / Years::period::den}, + {Unit::YEARS10, Years10::period::num / Years10::period::den}, + {Unit::YEARS30, Years30::period::num / Years30::period::den}, + {Unit::CENTURY, Centuries::period::num / Centuries::period::den}, + {Unit::HOURS3, Hours3::period::num / Hours3::period::den}, + {Unit::HOURS6, Hours6::period::num / Hours6::period::den}, + {Unit::HOURS12, Hours12::period::num / Hours12::period::den}, + {Unit::SECOND, Seconds::period::num / Seconds::period::den}, + {Unit::MINUTES15, Minutes15::period::num / Minutes15::period::den}, + {Unit::MINUTES30, Minutes30::period::num / Minutes30::period::den}, + }; + return map[code]; + } +}; + + class Step { public: Step() : value_(0), unit_(Unit::SECOND) {} - Step(int value, long indicatorOfUnitOfTimeRange); - Step(int value, Unit unit); + Step(int value, long unit); + explicit Step(const std::string& str); int value() const { return value_; } - Unit unit() const { return unit_; } - char* unit_str() const; + std::string unit_as_str() const; + long unit_as_long() const; + void hide_hour_unit() { hide_hour_unit_ = true; } Step& optimizeUnit(); - Step& setUnit(Unit new_unit); + Step& setUnit(std::string new_unit); + Step& setUnit(long new_unit); + double getDoubleValue(long unit) const; bool operator==(const Step& other) const; friend std::pair findCommonUnits(Step startStep, Step endStep); friend Step operator+(const Step step1, const Step step2); private: - std::map unitMap_ = { - {Unit::SECOND, 0}, + long unit() const { return unit_; } + Step& setUnit(Unit new_unit); + Step(int value, Unit unit); + std::vector> unitMap_ = { + {Unit::SECOND, 1}, {Unit::MINUTE, 60}, - {Unit::HOUR, 60}, - {Unit::DAY, 24} + //{Unit::MINUTES15, 900}, + //{Unit::MINUTES30, 1800}, + {Unit::HOUR, 3600}, + //{Unit::HOURS3, 10800}, + //{Unit::HOURS6, 21600}, + //{Unit::HOURS12, 43200}, + {Unit::DAY, 86400}, + {Unit::MONTH, 2592000}, + //{Unit::YEAR, 31536000}, + //{Unit::YEARS10, 315360000}, + //{Unit::YEARS30, 946080000}, + //{Unit::CENTURY, 3153600000}, }; int value_; Unit unit_; + Unit default_unit_ = Unit::HOUR; + bool hide_hour_unit_ = false; }; std::pair findCommonUnits(Step, Step); +std::string parse_step(std::string step); +std::vector parse_range(const std::string& range_str); diff --git a/tools/grib_ls.cc b/tools/grib_ls.cc index 44c8dec7f..2f16c022a 100644 --- a/tools/grib_ls.cc +++ b/tools/grib_ls.cc @@ -15,6 +15,7 @@ grib_option grib_options[] = { { "f", 0, 0, 1, 0, 0 }, { "p:", 0, 0, 0, 1, 0 }, { "F:", 0, 0, 1, 1, "%g" }, + { "y", 0, 0, 0, 1, 0 }, { "P:", 0, 0, 0, 1, 0 }, { "w:", 0, 0, 0, 1, 0 }, { "j", 0, "JSON output\n", 0, 1, 0 }, diff --git a/tools/grib_options.cc b/tools/grib_options.cc index 6f1af95fe..3e874369f 100644 --- a/tools/grib_options.cc +++ b/tools/grib_options.cc @@ -39,6 +39,7 @@ static grib_options_help grib_options_help_list[] = { { "e:", "tolerance", "\n\t\tOnly values whose difference is more than tolerance are considered different.\n" }, { "f", 0, "Force. Force the execution not to fail on error.\n" }, { "F:", "format", "\n\t\tC style format for floating-point values.\n" }, + { "y", "future", "\n\t\tFuture output format.\n" }, { "g", 0, "Copy GTS header. \n" }, { "G", 0, "GRIBEX compatibility mode.\n" }, { "i:", "index", @@ -250,6 +251,10 @@ int grib_process_runtime_options(grib_context* context, int argc, char** argv, g if (grib_options_on("X:")) options->infile_offset = atol(grib_options_get_option("X:")); + if (grib_options_on("y")) { + options->step_output_format = strdup("future"); + } + #ifndef ECCODES_ON_WINDOWS /* Check at compile time to ensure our file offset is at least 64 bits */ COMPILE_TIME_ASSERT(sizeof(options->infile_offset) >= 8); diff --git a/tools/grib_tools.cc b/tools/grib_tools.cc index 8b6becee7..3fc6eb708 100644 --- a/tools/grib_tools.cc +++ b/tools/grib_tools.cc @@ -9,6 +9,7 @@ */ #include "grib_tools.h" +#include "step_optimizer.h" #include #if HAVE_LIBJASPER @@ -112,7 +113,8 @@ static grib_runtime_options global_options = { 0, /* skip_all */ {{0,},}, /* grib_values tolerance[MAX_KEYS] */ 0, /* infile_offset */ - 0 /* JSON output */ + 0, /* JSON output */ + 0, /* step output format */ }; static grib_handle* grib_handle_new_from_file_x(grib_context* c, FILE* f, int mode, int headers_only, int* err) @@ -405,6 +407,11 @@ static int grib_tool_without_orderby(grib_runtime_options* options) continue; } + if (options->step_output_format) { + size_t step_output_format_size = strlen(options->step_output_format); + grib_set_string(h, "stepOutputFormat", options->step_output_format, &step_output_format_size); + } + grib_tool_new_handle_action(options, h); grib_print_key_values(options, h); @@ -1194,7 +1201,17 @@ void grib_print_key_values(grib_runtime_options* options, grib_handle* h) break; case GRIB_TYPE_LONG: ret = grib_get_long(h, options->print_keys[i].name, &lvalue); - snprintf(value, 32, "%ld", lvalue); + if ( + (strcmp(options->print_keys[i].name, "indicatorOfUnitOfTimeRange") == 0) || + (strcmp(options->print_keys[i].name, "indicatorOfUnitForTimeRange") == 0) + ) + { + snprintf(value, 32, "%s", StepUnitsTable::to_str(lvalue).c_str()); + } + else + { + snprintf(value, 32, "%ld", lvalue); + } break; case GRIB_TYPE_BYTES: ret = grib_get_string(h, options->print_keys[i].name, value, &len); diff --git a/tools/grib_tools.h b/tools/grib_tools.h index ef9ed42c1..9375083d9 100644 --- a/tools/grib_tools.h +++ b/tools/grib_tools.h @@ -16,6 +16,7 @@ #endif #include "grib_api_internal.h" +#include #include #ifndef ECCODES_ON_WINDOWS #include @@ -174,6 +175,7 @@ typedef struct grib_runtime_options grib_values tolerance[MAX_KEYS]; off_t infile_offset; int json_output; + char* step_output_format; } grib_runtime_options; extern grib_option grib_options[]; From a9b9bfe17cf8e078e20b12e86b7279b54803ae2a Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 10 Aug 2023 08:42:44 +0000 Subject: [PATCH 010/125] ECC-1620: unit support in grib_set (and more) (buggy) --- definitions/grib2/boot.def | 1 + .../grib2/template.4.forecast_time.def | 5 +- src/grib_accessor_class_g2end_step.cc | 364 ++++++++++++------ src/grib_accessor_class_g2step_range.cc | 125 ++++-- ...grib_accessor_class_step_human_readable.cc | 2 +- src/grib_accessor_class_step_in_units.cc | 214 +++++++--- src/step_optimizer.cc | 247 ++++++++---- src/step_optimizer.h | 190 ++++++++- tools/grib_ls.cc | 1 + tools/grib_options.cc | 5 + tools/grib_tools.cc | 21 +- tools/grib_tools.h | 2 + 12 files changed, 903 insertions(+), 274 deletions(-) diff --git a/definitions/grib2/boot.def b/definitions/grib2/boot.def index 32f262bef..cd90c57d1 100644 --- a/definitions/grib2/boot.def +++ b/definitions/grib2/boot.def @@ -17,6 +17,7 @@ constant million = 1000000 : hidden; constant grib2divider = 1000000; alias extraDimensionPresent=zero; transient angleSubdivisions=grib2divider; # micro degrees +transient stepOutputFormat=""; meta gts_header gts_header() : no_copy,hidden,read_only; meta gts_TTAAii gts_header(20,6) : no_copy,hidden,read_only; diff --git a/definitions/grib2/template.4.forecast_time.def b/definitions/grib2/template.4.forecast_time.def index 662310fc6..1f31f48c7 100644 --- a/definitions/grib2/template.4.forecast_time.def +++ b/definitions/grib2/template.4.forecast_time.def @@ -10,9 +10,10 @@ 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 +;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; +;codetable[1] stepUnits 'stepUnits.table' = defaultStepUnits : transient,dump,no_copy; +codetable[1] stepUnits 'stepUnits.table' = 255: transient,dump,no_copy; # Forecast time in units defined by previous octet (GRIB-29: supports negative forecast time) signed[4] forecastTime : dump; diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 285a30085..1388cdeed 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -9,6 +9,9 @@ */ #include "grib_api_internal.h" +#include "step_optimizer.h" +#include + /* This is used by make_class.pl @@ -55,6 +58,10 @@ 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 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 void dump(grib_accessor*, grib_dumper*); static void init(grib_accessor*, const long, grib_arguments*); @@ -107,12 +114,12 @@ 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 */ 0, /* pack_float */ - 0, /* unpack_double */ + &unpack_double, /* unpack_double */ 0, /* unpack_float */ - 0, /* pack_string */ - 0, /* unpack_string */ + &pack_string, /* pack_string */ + &unpack_string, /* unpack_string */ 0, /* pack_string_array */ 0, /* unpack_string_array */ 0, /* pack_bytes */ @@ -233,27 +240,36 @@ static int convert_time_range( Assert(lengthOfTimeRange != NULL); if (indicatorOfUnitForTimeRange != 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; + Step step{(int) *lengthOfTimeRange, indicatorOfUnitForTimeRange}; + if (stepUnits != 255) { + step.setUnit(stepUnits); } else { - u2sf_step_unit = u2s[stepUnits]; + step.setUnit(indicatorOfUnitForTimeRange); } - 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; + *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; } return GRIB_SUCCESS; @@ -391,109 +407,237 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) } } +// 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); + grib_handle* h = grib_handle_of_accessor(a); + int ret = 0; - int err = 0; + Step step{(int) *val, StepUnitsTable::to_long("h")}; + ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit_as_long()); + if (ret) + return ret; - long year; - long month; - long day; - long hour; - long minute; - long second; + ret = grib_set_long_internal(h, "lengthOfTimeRange", step.value()); + if (ret) + return ret; + return GRIB_SUCCESS; - 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; - long coded_time_range, time_range, typeOfTimeIncrement; +// grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; +// grib_handle* h = grib_handle_of_accessor(a); - double dend, dstep; +// int err = 0; - /*point in time */ - if (self->year == NULL) { - err = grib_set_long_internal(h, self->start_step, *val); - return err; +// long year; +// long month; +// long day; +// long hour; +// long minute; +// long second; + +// 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; + +// 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; +} + +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 step = Step(parse_step(std::string(val))); + + ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit_as_long()); + if (ret) + return ret; + + ret = grib_set_long_internal(h, "lengthOfTimeRange", step.value()); + if (ret) + return ret; + + return GRIB_SUCCESS; +} + + +//static int unpack_string(grib_accessor* a, char* val, size_t* len) { +// throw std::runtime_error("g2end_step: unpack_string() is not implemented"); +// //return GRIB_NOT_IMPLEMENTED; +//} + +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; + + long unit; + ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit); + if (ret) + return ret; + + long value; + ret = grib_get_long_internal(h, "lengthOfTimeRange", &value); + if (ret) + return ret; + + Step step{(int) value, unit}; + + sprintf(val, "%d%s", step.value(), step.unit_as_str().c_str()); + + 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 unit; + ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit); + if (ret) + return ret; + + + long stepUnits; + ret = grib_get_long_internal(h, "stepUnits", &stepUnits); + if (ret) + return ret; + + Step step; + if (stepUnits != 255) { + step = Step((int) *val, stepUnits); + } + else { + step = Step((int) *val, unit); } - 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; + ret = grib_set_long_internal(h, "lengthOfTimeRange", step.value()); + if (ret) + return ret; + ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit_as_long()); + if (ret) + return ret; - 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; + return ret; +} - time_range = *val - start_step; +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; - if (time_range < 0) { - grib_context_log(h->context, GRIB_LOG_ERROR, - "endStep < startStep (%ld < %ld)", *val, start_step); - return GRIB_WRONG_STEP; + long unit; + ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit); + if (ret) + 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; + + if (stepUnits != 255) { + Step step = Step(value, unit); + *val = step.getDoubleValue(stepUnits); } - - 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; + else { + Step step = Step(value, unit); + *val = step.value(); } return GRIB_SUCCESS; diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 5228163fe..8c8a35b23 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_optimizer.h" +#include /* This is used by make_class.pl @@ -140,22 +141,6 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) size_t size = 0; //long start = 0, theEnd = 0; - //0 m Minute - //1 h Hour - //2 D Day - //3 M Month - //4 Y Year - //5 10Y Decade - //6 30Y Normal (30 years) - //7 C Century - //10 3h 3 hours - //11 6h 6 hours - //12 12h 12 hours - //13 15m 15 minutes - //14 30m 30 minutes - //254 s Second - - //ret = grib_get_long_internal(h, self->startStep, &start); if (ret) return ret; @@ -169,14 +154,29 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; + size_t stepUnitsSize = 128; + char stepUnits[stepUnitsSize]; + ret = grib_get_string_internal(h, "stepUnits", stepUnits, &stepUnitsSize); + if (ret) + return ret; + //printf("stepUnits=%s\n", stepUnits); + + size_t stepOutputFormatSize = 128; + char stepOutputFormat[stepOutputFormatSize]; + ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize); + if (ret) + return ret; + //printf("stepOutputFormat=%s\n", stepOutputFormat); + Step step_a{(int) forecastTime, indicatorOfUnitOfTimeRange}; step_a.optimizeUnit(); - if (ret) - return ret; + if (strcmp(stepOutputFormat, "future") != 0) { + step_a.hide_hour_unit(); + } if (self->endStep == NULL) { - snprintf(buf, sizeof(buf), "%d%s", step_a.value(), step_a.unit_str()); + snprintf(buf, sizeof(buf), "%d%s", step_a.value(), step_a.unit_as_str().c_str()); } else { long indicatorOfUnitForTimeRange; @@ -193,11 +193,16 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) step_b.optimizeUnit(); auto [a, b] = findCommonUnits(step_a, step_b); + if (strcmp(stepOutputFormat, "future") != 0) { + step_b.hide_hour_unit(); + a.hide_hour_unit(); + b.hide_hour_unit(); + } if (a.value() == 0) { - snprintf(buf, sizeof(buf), "0-%d%s", step_b.value(), step_b.unit_str()); + snprintf(buf, sizeof(buf), "0-%d%s", step_b.value(), step_b.unit_as_str().c_str()); } else { - snprintf(buf, sizeof(buf), "%d-%d%s", a.value(), b.value(), a.unit_str()); + snprintf(buf, sizeof(buf), "%d-%d%s", a.value(), b.value(), step_b.unit_as_str().c_str()); } } @@ -213,29 +218,83 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return GRIB_SUCCESS; } + static int pack_string(grib_accessor* a, const char* val, size_t* len) { grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; grib_handle* h = grib_handle_of_accessor(a); - - long start = 0, theEnd = -1; int ret = 0; - char *p = NULL, *q = NULL; - start = strtol(val, &p, 10); - theEnd = start; + std::vector steps = parse_range(val); + if (steps.size() == 0) { + return GRIB_INVALID_ARGUMENT; + } + //ret = grib_set_long_internal(h, self->startStep, steps[0].value()); + //if (ret) + // return ret; - if (*p != 0) - theEnd = strtol(++p, &q, 10); - ret = grib_set_long_internal(h, self->startStep, start); - if (ret) - return ret; + //printf("val: %s\n", val); - if (self->endStep != NULL) { - ret = grib_set_long_internal(h, self->endStep, theEnd); + if (steps.size() == 1) { + //printf("unit_str 1: %s\n", steps[0].unit_as_str().c_str()); + steps[0].optimizeUnit(); + ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", steps[0].unit_as_long()); + if (ret) + return ret; + + ret = grib_set_long_internal(h, "forecastTime", steps[0].value()); if (ret) return ret; } + else if (steps.size() == 2) { + //ret = grib_set_long_internal(h, self->endStep, steps[1].value()); + //if (ret) + // return ret; + //printf("unit_str 2: %s\n", steps[1].unit_as_str().c_str()); + + steps[0].optimizeUnit(); + steps[1].optimizeUnit(); + auto [a, b] = findCommonUnits(steps[0], steps[1]); + + ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", a.unit_as_long()); + if (ret) + return ret; + ret = grib_set_long_internal(h, "forecastTime", a.value()); + if (ret) + return ret; + + + ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", b.unit_as_long()); + if (ret) + return ret; + ret = grib_set_long_internal(h, "lengthOfTimeRange", b.value()); + if (ret) + return ret; + } + else { + std::string msg = std::string("Invalid range: ") + val; + throw std::runtime_error(msg); + } + + + //long start = 0, theEnd = -1; + //int ret = 0; + //char *p = NULL, *q = NULL; + + //start = strtol(val, &p, 10); + //theEnd = start; + + //if (*p != 0) + // theEnd = strtol(++p, &q, 10); + //ret = grib_set_long_internal(h, self->startStep, start); + //if (ret) + // return ret; + + //if (self->endStep != NULL) { + // ret = grib_set_long_internal(h, self->endStep, theEnd); + // if (ret) + // return ret; + //} return 0; } diff --git a/src/grib_accessor_class_step_human_readable.cc b/src/grib_accessor_class_step_human_readable.cc index 24c7ac823..d9fe32d25 100644 --- a/src/grib_accessor_class_step_human_readable.cc +++ b/src/grib_accessor_class_step_human_readable.cc @@ -137,7 +137,7 @@ static int get_step_human_readable(grib_handle* h, char* result, size_t* length) auto stepOptimizer = Step(step, indicator); stepOptimizer.optimizeUnit(); - snprintf(result, 1024, "%d%s", stepOptimizer.value(), stepOptimizer.unit_str()); + snprintf(result, 1024, "%d%s", stepOptimizer.value(), stepOptimizer.unit_as_str().c_str()); *length = strlen(result); return GRIB_SUCCESS; diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index acf570c19..99d493bd5 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -9,6 +9,8 @@ */ #include "grib_api_internal.h" +#include "step_optimizer.h" +#include /* This is used by make_class.pl @@ -39,6 +41,10 @@ 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 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 void dump(grib_accessor*, grib_dumper*); static void init(grib_accessor*, const long, grib_arguments*); @@ -78,12 +84,12 @@ 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 */ 0, /* pack_float */ - 0, /* unpack_double */ + &unpack_double, /* unpack_double */ 0, /* unpack_float */ - 0, /* pack_string */ - 0, /* unpack_string */ + &pack_string, /* pack_string */ + &unpack_string, /* unpack_string */ 0, /* pack_string_array */ 0, /* unpack_string_array */ 0, /* pack_bytes */ @@ -214,52 +220,172 @@ 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 err = 0; - long codedStep, codedUnits, stepUnits; - long oldStep = 0; - long indicatorOfUnitForTimeRange, lengthOfTimeRange; + grib_handle* h = grib_handle_of_accessor(a); + int ret = 0; - if ((err = grib_get_long_internal(h, self->codedUnits, &codedUnits))) - return err; - if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits))) - return err; + Step step{(int) *val, StepUnitsTable::to_long("h")}; + ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", step.unit_as_long()); + if (ret) + return ret; - unpack_long(a, &oldStep, len); + ret = grib_set_long_internal(h, "forecastTime", step.value()); + if (ret) + return ret; + return GRIB_SUCCESS; - if (stepUnits != codedUnits) { - codedStep = *val * u2s[stepUnits]; - if (codedStep % u2s2[codedUnits] != 0) { - codedUnits = stepUnits; - err = grib_set_long_internal(h, self->codedUnits, codedUnits); - if (err != GRIB_SUCCESS) - return err; - codedStep = *val; - } - else { - codedStep = codedStep / u2s2[codedUnits]; - } + //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; + //long indicatorOfUnitForTimeRange, lengthOfTimeRange; + + //if ((err = grib_get_long_internal(h, self->codedUnits, &codedUnits))) + // return err; + //if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits))) + // return err; + + //unpack_long(a, &oldStep, len); + + //if (stepUnits != codedUnits) { + // codedStep = *val * u2s[stepUnits]; + // if (codedStep % u2s2[codedUnits] != 0) { + // codedUnits = stepUnits; + // err = grib_set_long_internal(h, self->codedUnits, codedUnits); + // if (err != GRIB_SUCCESS) + // return err; + // codedStep = *val; + // } + // else { + // codedStep = codedStep / u2s2[codedUnits]; + // } + //} + //else { + // codedStep = *val; + //} + + //if (self->indicatorOfUnitForTimeRange) { + // if ((err = grib_get_long_internal(h, + // self->indicatorOfUnitForTimeRange, &indicatorOfUnitForTimeRange))) + // return err; + // if ((err = grib_get_long_internal(h, + // self->lengthOfTimeRange, &lengthOfTimeRange))) + // return err; + // if (codedUnits == indicatorOfUnitForTimeRange) + // lengthOfTimeRange -= codedStep - oldStep; + // else + // lengthOfTimeRange -= codedStep * u2s2[codedUnits] / u2s2[indicatorOfUnitForTimeRange]; + // lengthOfTimeRange = lengthOfTimeRange > 0 ? lengthOfTimeRange : 0; + // err = grib_set_long_internal(grib_handle_of_accessor(a), self->lengthOfTimeRange, lengthOfTimeRange); + // if (err != GRIB_SUCCESS) + // return err; + //} + + //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) { + 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, "indicatorOfUnitOfTimeRange", step.unit_as_long()); + if (ret) + return ret; + + ret = grib_set_long_internal(h, "forecastTime", step.value()); + if (ret) + return ret; + + return GRIB_SUCCESS; +} + +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; + + long unit; + ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &unit); + if (ret) + return ret; + + long value; + ret = grib_get_long_internal(h, "forecastTime", &value); + if (ret) + return ret; + + Step step{(int) value, unit}; + sprintf(val, "%d%s", step.value(), step.unit_as_str().c_str()); + + return GRIB_SUCCESS; +} + + +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, "indicatorOfUnitOfTimeRange", &unit); + if (ret) + return ret; + + + long stepUnits; + ret = grib_get_long_internal(h, self->stepUnits, &stepUnits); + if (ret) + return ret; + + Step step; + if (stepUnits != 255) { + step = Step((int) *val, stepUnits); } else { - codedStep = *val; + step = Step((int) *val, unit); } - if (self->indicatorOfUnitForTimeRange) { - if ((err = grib_get_long_internal(h, - self->indicatorOfUnitForTimeRange, &indicatorOfUnitForTimeRange))) - return err; - if ((err = grib_get_long_internal(h, - self->lengthOfTimeRange, &lengthOfTimeRange))) - return err; - if (codedUnits == indicatorOfUnitForTimeRange) - lengthOfTimeRange -= codedStep - oldStep; - else - lengthOfTimeRange -= codedStep * u2s2[codedUnits] / u2s2[indicatorOfUnitForTimeRange]; - lengthOfTimeRange = lengthOfTimeRange > 0 ? lengthOfTimeRange : 0; - err = grib_set_long_internal(grib_handle_of_accessor(a), self->lengthOfTimeRange, lengthOfTimeRange); - if (err != GRIB_SUCCESS) - return err; - } + ret = grib_set_long_internal(h, "forecastTime", step.value()); + if (ret) + return ret; + ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", step.unit_as_long()); + if (ret) + return ret; - return grib_set_long_internal(grib_handle_of_accessor(a), self->codedStep, codedStep); + return ret; +} + + +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 = 0; + + long unit; + ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &unit); + if (ret) + return ret; + + long value; + ret = grib_get_long_internal(h, "forecastTime", &value); + if (ret) + return ret; + + long stepUnits; + ret = grib_get_long_internal(h, self->stepUnits, &stepUnits); + if (ret) + return ret; + + if (stepUnits != 255) { + Step step = Step(value, unit); + *val = step.getDoubleValue(stepUnits); + } + else { + Step step = Step(value, unit); + *val = step.value(); + } + + return GRIB_SUCCESS; } diff --git a/src/step_optimizer.cc b/src/step_optimizer.cc index 5ea2c6ced..e65611712 100644 --- a/src/step_optimizer.cc +++ b/src/step_optimizer.cc @@ -6,52 +6,65 @@ #include "step_optimizer.h" -char* Step::unit_str() const { - static char seconds[] = "s"; - static char minutes[] = "m"; - static char hours[] = "h"; - static char days[] = "d"; - switch (unit_) { - case Unit::SECOND: - return seconds; - case Unit::MINUTE: - return minutes; - case Unit::HOUR: - return hours; - case Unit::DAY: - return days; - default: - std::string msg = "Unknown unit: " + std::to_string(static_cast(unit_)); - throw std::runtime_error(msg); + +std::string parse_step(std::string step) { + if (step.find_first_of("smhdMYC") == std::string::npos) { + step += "h"; } + return step; } -Step::Step(int value, long indicatorOfUnitOfTimeRange) { + +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; +} + + +std::string Step::unit_as_str() const { + if ((unit_ == Unit::HOUR) && hide_hour_unit_) + return std::string(""); + else + return StepUnitsTable::to_str(unit_); +} + +long Step::unit_as_long() const { + return unit_; +} + +Step::Step(int value, long 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."); } - Unit u = Unit::UNKNOWN; - switch (indicatorOfUnitOfTimeRange) { - case 0: - u = Unit::MINUTE; - break; - case 1: - u = Unit::HOUR; - break; - case 2: - u = Unit::DAY; - break; - case 254: - u = Unit::SECOND; - break; - default: - std::string msg = "Unknown indicatorOfUnitOfTimeRange: " + std::to_string(indicatorOfUnitOfTimeRange); - throw std::runtime_error(msg); - } value_ = value; - unit_ = u; + unit_ = StepUnitsTable::to_unit(unit); +} + +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_ = StepUnitsTable::to_unit(u_str); } Step::Step(int value, Unit u) { @@ -67,22 +80,51 @@ Step& Step::optimizeUnit() { if (value_ == 0) { return *this; } - std::map::iterator it = unitMap_.find(unit_); - ++it; - for (; it != unitMap_.end(); ++it){ - Unit u = it->first; - int multiplier = it->second; - if (value_ % multiplier == 0) { - value_ /= multiplier; - unit_ = u; - } - else { + + Seconds duration(0); + switch (unit_) { + 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: " + StepUnitsTable::to_str(unit_); + throw std::runtime_error(msg); + } + + for (auto it = unitMap_.end(); it != unitMap_.begin();) { + --it; + int multiplier = it->second; + if (duration.count() % multiplier == 0) { + value_ = duration.count() / multiplier; + unit_ = it->first; + return *this; } } return *this; } +Step& Step::setUnit(std::string new_unit) { + setUnit(StepUnitsTable::to_unit(new_unit)); + return *this; +} + +Step& Step::setUnit(long new_unit) { + setUnit(StepUnitsTable::to_unit(new_unit)); + return *this; +} + Step& Step::setUnit(Unit new_unit) { if (value_ == 0) { unit_ = new_unit; @@ -91,30 +133,101 @@ Step& Step::setUnit(Unit new_unit) { if (unit_ == new_unit) { return *this; } - std::map::iterator it = unitMap_.find(unit_); - if (new_unit > unit_) { - ++it; - for (; it != unitMap_.find(new_unit); ++it) { - int multiplier = it->second; - if (value_ % multiplier == 0) { - throw std::exception(); - } - value_ /= multiplier; - unit_ = it->first; - } + Seconds duration(0); + switch (unit_) { + 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: " + std::to_string(static_cast(unit_)); + throw std::runtime_error(msg); } - else { - int multiplier = it->second; - for (; it != unitMap_.find(new_unit);) { - value_ *= multiplier; - --it; - unit_ = it->first; - multiplier = it->second; - } + + switch (new_unit) { + case Unit::SECOND: + value_ = duration.count(); + break; + case Unit::MINUTE: + value_ = std::chrono::duration_cast(duration).count(); + break; + case Unit::HOUR: + value_ = std::chrono::duration_cast(duration).count(); + break; + case Unit::DAY: + value_ = std::chrono::duration_cast(duration).count(); + break; + case Unit::MONTH: + value_ = std::chrono::duration_cast(duration).count(); + break; + default: + std::string msg = "Unknown unit: " + std::to_string(static_cast(new_unit)); + throw std::runtime_error(msg); } + unit_ = new_unit; + return *this; } +double Step::getDoubleValue(long new_unit) const { + Seconds duration(0); + switch (unit_) { + 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: " + std::to_string(static_cast(unit_)); + throw std::runtime_error(msg); + } + + double value; + switch (new_unit) { + case Unit::SECOND: + value = std::chrono::duration_cast(duration).count(); + break; + case Unit::MINUTE: + value = std::chrono::duration_cast(duration).count(); + break; + case Unit::HOUR: + value = std::chrono::duration_cast(duration).count(); + break; + case Unit::DAY: + value = std::chrono::duration_cast(duration).count(); + break; + case Unit::MONTH: + value = std::chrono::duration_cast(duration).count(); + break; + default: + std::string msg = "Unknown unit: " + std::to_string(static_cast(new_unit)); + throw std::runtime_error(msg); + } + + return value; +} + bool Step::operator==(const Step& other) const { if (value_ == other.value_ && unit_ == other.unit_) { return true; @@ -131,7 +244,7 @@ Step operator+(const Step step1, const Step step2) { std::pair findCommonUnits(Step startStep, Step endStep) { if (startStep.value_ == 0 || endStep.value_ == 0) { if (startStep.value_ == 0 && endStep.value_ == 0) { - Unit unit = std::max(startStep.unit_, endStep.unit_); + Unit unit = StepUnitsTable::unit_duration(startStep.unit_) > StepUnitsTable::unit_duration(endStep.unit_) ? startStep.unit_ : endStep.unit_; startStep.setUnit(unit); endStep.setUnit(unit); } diff --git a/src/step_optimizer.h b/src/step_optimizer.h index 913fc30de..9b88fcd70 100644 --- a/src/step_optimizer.h +++ b/src/step_optimizer.h @@ -5,40 +5,200 @@ #include #include #include +#include +#include +#include -enum class Unit { - SECOND, - MINUTE, - HOUR, - DAY, - UNKNOWN + +enum Unit : long { + MINUTE = 0, + HOUR = 1, + DAY = 2, + MONTH = 3, + YEAR = 4, + YEARS10 = 5, + YEARS30 = 6, + CENTURY = 7, + HOURS3 = 10, + HOURS6 = 11, + HOURS12 = 12, + SECOND = 13, + MINUTES15 = 14, + MINUTES30 = 15, + MISSING = 255, }; +using Minutes = std::chrono::duration>; +using Hours = std::chrono::duration>; +using Days = std::chrono::duration>; +using Months = std::chrono::duration>; +using Years = std::chrono::duration>; +using Years10 = std::chrono::duration>; +using Years30 = std::chrono::duration>; +using Centuries = std::chrono::duration>; +using Hours3 = std::chrono::duration>; +using Hours6 = std::chrono::duration>; +using Hours12 = std::chrono::duration>; +using Seconds = std::chrono::duration>; +using Minutes15 = std::chrono::duration>; +using Minutes30 = std::chrono::duration>; +using Missing = std::chrono::duration>; + +using MinutesDouble = std::chrono::duration>; +using HoursDouble = std::chrono::duration>; +using DaysDouble = std::chrono::duration>; +using MonthsDouble = std::chrono::duration>; +using YearsDouble = std::chrono::duration>; +using Years10Double = std::chrono::duration>; +using Years30Double = std::chrono::duration>; +using CenturiesDouble = std::chrono::duration>; +using Hours3Double = std::chrono::duration>; +using Hours6Double = std::chrono::duration>; +using Hours12Double = std::chrono::duration>; +using SecondsDouble = std::chrono::duration>; +using Minutes15Double = std::chrono::duration>; +using Minutes30Double = std::chrono::duration>; +using MissingDouble = std::chrono::duration>; + +class StepUnitsTable{ +private: + StepUnitsTable() { + } +public: + static Unit to_unit(const std::string& str) { + static std::map map = { + {"m", Unit::MINUTE}, + {"h", Unit::HOUR}, + {"d", Unit::DAY}, + {"M", Unit::MONTH}, + {"Y", Unit::YEAR}, + {"10Y", Unit::YEARS10}, + {"30Y", Unit::YEARS30}, + {"C", Unit::CENTURY}, + {"3h", Unit::HOURS3}, + {"6h", Unit::HOURS6}, + {"12h", Unit::HOURS12}, + {"s", Unit::SECOND}, + {"15m", Unit::MINUTES15}, + {"30m", Unit::MINUTES30}, + {"255", Unit::MISSING}, + }; + return map[str]; + } + + static long to_long(const std::string& str) { + return to_unit(str); + } + + static Unit to_unit(long code) { + static std::map map = { + {Unit::MINUTE, Unit::MINUTE}, + {Unit::HOUR, Unit::HOUR}, + {Unit::DAY, Unit::DAY}, + {Unit::MONTH, Unit::MONTH}, + {Unit::YEAR, Unit::YEAR}, + {Unit::YEARS10, Unit::YEARS10}, + {Unit::YEARS30, Unit::YEARS30}, + {Unit::CENTURY, Unit::CENTURY}, + {Unit::HOURS3, Unit::HOURS3}, + {Unit::HOURS6, Unit::HOURS6}, + {Unit::HOURS12, Unit::HOURS12}, + {Unit::SECOND, Unit::SECOND}, + {Unit::MINUTES15, Unit::MINUTES15}, + {Unit::MINUTES30, Unit::MINUTES30}, + {Unit::MISSING, Unit::MISSING}, + }; + return map[code]; + } + + static std::string to_str(long code) { + static std::map map = { + {Unit::MINUTE, "m"}, + {Unit::HOUR, "h"}, + {Unit::DAY, "d"}, + {Unit::MONTH, "M"}, + {Unit::YEAR, "Y"}, + {Unit::YEARS10, "10Y"}, + {Unit::YEARS30, "30Y"}, + {Unit::CENTURY, "C"}, + {Unit::HOURS3, "3h"}, + {Unit::HOURS6, "6h"}, + {Unit::HOURS12, "12h"}, + {Unit::SECOND, "s"}, + {Unit::MINUTES15, "15m"}, + {Unit::MINUTES30, "30m"}, + {Unit::MISSING, "255"}, + }; + return map[code]; + } + + static double unit_duration(long code) { + static std::map map = { + {Unit::MINUTE, Minutes::period::num / Minutes::period::den}, + {Unit::HOUR, Hours::period::num / Hours::period::den}, + {Unit::DAY, Days::period::num / Days::period::den}, + {Unit::MONTH, Months::period::num / Months::period::den}, + {Unit::YEAR, Years::period::num / Years::period::den}, + {Unit::YEARS10, Years10::period::num / Years10::period::den}, + {Unit::YEARS30, Years30::period::num / Years30::period::den}, + {Unit::CENTURY, Centuries::period::num / Centuries::period::den}, + {Unit::HOURS3, Hours3::period::num / Hours3::period::den}, + {Unit::HOURS6, Hours6::period::num / Hours6::period::den}, + {Unit::HOURS12, Hours12::period::num / Hours12::period::den}, + {Unit::SECOND, Seconds::period::num / Seconds::period::den}, + {Unit::MINUTES15, Minutes15::period::num / Minutes15::period::den}, + {Unit::MINUTES30, Minutes30::period::num / Minutes30::period::den}, + }; + return map[code]; + } +}; + + class Step { public: Step() : value_(0), unit_(Unit::SECOND) {} - Step(int value, long indicatorOfUnitOfTimeRange); - Step(int value, Unit unit); + Step(int value, long unit); + explicit Step(const std::string& str); int value() const { return value_; } - Unit unit() const { return unit_; } - char* unit_str() const; + std::string unit_as_str() const; + long unit_as_long() const; + void hide_hour_unit() { hide_hour_unit_ = true; } Step& optimizeUnit(); - Step& setUnit(Unit new_unit); + Step& setUnit(std::string new_unit); + Step& setUnit(long new_unit); + double getDoubleValue(long unit) const; bool operator==(const Step& other) const; friend std::pair findCommonUnits(Step startStep, Step endStep); friend Step operator+(const Step step1, const Step step2); private: - std::map unitMap_ = { - {Unit::SECOND, 0}, + long unit() const { return unit_; } + Step& setUnit(Unit new_unit); + Step(int value, Unit unit); + std::vector> unitMap_ = { + {Unit::SECOND, 1}, {Unit::MINUTE, 60}, - {Unit::HOUR, 60}, - {Unit::DAY, 24} + //{Unit::MINUTES15, 900}, + //{Unit::MINUTES30, 1800}, + {Unit::HOUR, 3600}, + //{Unit::HOURS3, 10800}, + //{Unit::HOURS6, 21600}, + //{Unit::HOURS12, 43200}, + {Unit::DAY, 86400}, + {Unit::MONTH, 2592000}, + //{Unit::YEAR, 31536000}, + //{Unit::YEARS10, 315360000}, + //{Unit::YEARS30, 946080000}, + //{Unit::CENTURY, 3153600000}, }; int value_; Unit unit_; + Unit default_unit_ = Unit::HOUR; + bool hide_hour_unit_ = false; }; std::pair findCommonUnits(Step, Step); +std::string parse_step(std::string step); +std::vector parse_range(const std::string& range_str); diff --git a/tools/grib_ls.cc b/tools/grib_ls.cc index 44c8dec7f..2f16c022a 100644 --- a/tools/grib_ls.cc +++ b/tools/grib_ls.cc @@ -15,6 +15,7 @@ grib_option grib_options[] = { { "f", 0, 0, 1, 0, 0 }, { "p:", 0, 0, 0, 1, 0 }, { "F:", 0, 0, 1, 1, "%g" }, + { "y", 0, 0, 0, 1, 0 }, { "P:", 0, 0, 0, 1, 0 }, { "w:", 0, 0, 0, 1, 0 }, { "j", 0, "JSON output\n", 0, 1, 0 }, diff --git a/tools/grib_options.cc b/tools/grib_options.cc index 6f1af95fe..3e874369f 100644 --- a/tools/grib_options.cc +++ b/tools/grib_options.cc @@ -39,6 +39,7 @@ static grib_options_help grib_options_help_list[] = { { "e:", "tolerance", "\n\t\tOnly values whose difference is more than tolerance are considered different.\n" }, { "f", 0, "Force. Force the execution not to fail on error.\n" }, { "F:", "format", "\n\t\tC style format for floating-point values.\n" }, + { "y", "future", "\n\t\tFuture output format.\n" }, { "g", 0, "Copy GTS header. \n" }, { "G", 0, "GRIBEX compatibility mode.\n" }, { "i:", "index", @@ -250,6 +251,10 @@ int grib_process_runtime_options(grib_context* context, int argc, char** argv, g if (grib_options_on("X:")) options->infile_offset = atol(grib_options_get_option("X:")); + if (grib_options_on("y")) { + options->step_output_format = strdup("future"); + } + #ifndef ECCODES_ON_WINDOWS /* Check at compile time to ensure our file offset is at least 64 bits */ COMPILE_TIME_ASSERT(sizeof(options->infile_offset) >= 8); diff --git a/tools/grib_tools.cc b/tools/grib_tools.cc index 8b6becee7..3fc6eb708 100644 --- a/tools/grib_tools.cc +++ b/tools/grib_tools.cc @@ -9,6 +9,7 @@ */ #include "grib_tools.h" +#include "step_optimizer.h" #include #if HAVE_LIBJASPER @@ -112,7 +113,8 @@ static grib_runtime_options global_options = { 0, /* skip_all */ {{0,},}, /* grib_values tolerance[MAX_KEYS] */ 0, /* infile_offset */ - 0 /* JSON output */ + 0, /* JSON output */ + 0, /* step output format */ }; static grib_handle* grib_handle_new_from_file_x(grib_context* c, FILE* f, int mode, int headers_only, int* err) @@ -405,6 +407,11 @@ static int grib_tool_without_orderby(grib_runtime_options* options) continue; } + if (options->step_output_format) { + size_t step_output_format_size = strlen(options->step_output_format); + grib_set_string(h, "stepOutputFormat", options->step_output_format, &step_output_format_size); + } + grib_tool_new_handle_action(options, h); grib_print_key_values(options, h); @@ -1194,7 +1201,17 @@ void grib_print_key_values(grib_runtime_options* options, grib_handle* h) break; case GRIB_TYPE_LONG: ret = grib_get_long(h, options->print_keys[i].name, &lvalue); - snprintf(value, 32, "%ld", lvalue); + if ( + (strcmp(options->print_keys[i].name, "indicatorOfUnitOfTimeRange") == 0) || + (strcmp(options->print_keys[i].name, "indicatorOfUnitForTimeRange") == 0) + ) + { + snprintf(value, 32, "%s", StepUnitsTable::to_str(lvalue).c_str()); + } + else + { + snprintf(value, 32, "%ld", lvalue); + } break; case GRIB_TYPE_BYTES: ret = grib_get_string(h, options->print_keys[i].name, value, &len); diff --git a/tools/grib_tools.h b/tools/grib_tools.h index ef9ed42c1..9375083d9 100644 --- a/tools/grib_tools.h +++ b/tools/grib_tools.h @@ -16,6 +16,7 @@ #endif #include "grib_api_internal.h" +#include #include #ifndef ECCODES_ON_WINDOWS #include @@ -174,6 +175,7 @@ typedef struct grib_runtime_options grib_values tolerance[MAX_KEYS]; off_t infile_offset; int json_output; + char* step_output_format; } grib_runtime_options; extern grib_option grib_options[]; From 5ec09da607bf5cdd273fd84c184a303eea13cd1a Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Thu, 10 Aug 2023 09:17:02 +0000 Subject: [PATCH 011/125] Compiler warnings: unused variables --- src/grib_accessor_class_g2end_step.cc | 6 +++--- src/grib_accessor_class_g2step_range.cc | 2 +- src/grib_accessor_class_step_human_readable.cc | 2 +- src/grib_accessor_class_step_in_units.cc | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 1388cdeed..637e95689 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -410,7 +410,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) // 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_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; @@ -578,7 +578,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) { } static int pack_double(grib_accessor* a, const double* val, size_t* len) { - grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; + //grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; @@ -612,7 +612,7 @@ static int pack_double(grib_accessor* a, const 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_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 8c8a35b23..a279d90c6 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -221,7 +221,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { - grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; + //grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; diff --git a/src/grib_accessor_class_step_human_readable.cc b/src/grib_accessor_class_step_human_readable.cc index d9fe32d25..c54e793c8 100644 --- a/src/grib_accessor_class_step_human_readable.cc +++ b/src/grib_accessor_class_step_human_readable.cc @@ -122,7 +122,7 @@ static int get_native_type(grib_accessor* a) static int get_step_human_readable(grib_handle* h, char* result, size_t* length) { int err = 0; - size_t slen = 2; + //size_t slen = 2; long step; /* Change units to seconds (highest resolution) diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 99d493bd5..c3523afae 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -219,7 +219,7 @@ 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_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; @@ -285,7 +285,7 @@ static int pack_long(grib_accessor* a, const long* 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_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; @@ -302,7 +302,7 @@ static int pack_string(grib_accessor* a, const 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_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; From 8ce5263b2e41403516d408651bcfe8288946938d Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 11 Aug 2023 13:42:09 +0000 Subject: [PATCH 012/125] ECC-1620: Make almost all tests work --- definitions/grib2/boot.def | 3 +- .../grib2/template.4.forecast_time.def | 5 +- src/grib_accessor_class_g2end_step.cc | 217 ++++++++-------- src/grib_accessor_class_g2step_range.cc | 242 ++++++++++-------- ...grib_accessor_class_step_human_readable.cc | 50 +++- src/grib_accessor_class_step_in_units.cc | 20 +- src/step_optimizer.cc | 38 ++- src/step_optimizer.h | 17 +- tools/grib_dump.cc | 1 + tools/grib_set.cc | 1 + tools/grib_tools.cc | 21 +- 11 files changed, 345 insertions(+), 270 deletions(-) diff --git a/definitions/grib2/boot.def b/definitions/grib2/boot.def index cd90c57d1..0a16b2893 100644 --- a/definitions/grib2/boot.def +++ b/definitions/grib2/boot.def @@ -17,7 +17,8 @@ constant million = 1000000 : hidden; constant grib2divider = 1000000; alias extraDimensionPresent=zero; transient angleSubdivisions=grib2divider; # micro degrees -transient stepOutputFormat=""; +transient stepOutputFormat="default" : hidden; +transient forceStepUnits = 0 : hidden; meta gts_header gts_header() : no_copy,hidden,read_only; meta gts_TTAAii gts_header(20,6) : no_copy,hidden,read_only; diff --git a/definitions/grib2/template.4.forecast_time.def b/definitions/grib2/template.4.forecast_time.def index 1f31f48c7..662310fc6 100644 --- a/definitions/grib2/template.4.forecast_time.def +++ b/definitions/grib2/template.4.forecast_time.def @@ -10,10 +10,9 @@ 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 +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; -codetable[1] stepUnits 'stepUnits.table' = 255: transient,dump,no_copy; +codetable[1] stepUnits 'stepUnits.table' = defaultStepUnits : transient,dump,no_copy; # Forecast time in units defined by previous octet (GRIB-29: supports negative forecast time) signed[4] forecastTime : dump; diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 1388cdeed..e79a87562 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -114,12 +114,12 @@ static grib_accessor_class _grib_accessor_class_g2end_step = { 0, /* is_missing */ &pack_long, /* pack_long */ &unpack_long, /* unpack_long */ - &pack_double, /* pack_double */ + 0, //&pack_double, /* pack_double */ 0, /* pack_float */ - &unpack_double, /* unpack_double */ + 0, //&unpack_double, /* unpack_double */ 0, /* unpack_float */ - &pack_string, /* pack_string */ - &unpack_string, /* unpack_string */ + 0, //&pack_string, /* pack_string */ + 0, //&unpack_string, /* unpack_string */ 0, /* pack_string_array */ 0, /* unpack_string_array */ 0, /* pack_bytes */ @@ -414,121 +414,128 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - Step step{(int) *val, StepUnitsTable::to_long("h")}; - ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit_as_long()); - if (ret) + size_t stepOutputFormatSize = 128; + char stepOutputFormat[stepOutputFormatSize]; + if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) return ret; - ret = grib_set_long_internal(h, "lengthOfTimeRange", step.value()); - if (ret) - return ret; - return GRIB_SUCCESS; + if (strcmp(stepOutputFormat, "future") == 0) { + Step step{(int) *val, StepUnitsTable::to_long("h")}; + ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit_as_long()); + if (ret) + return ret; + ret = grib_set_long_internal(h, "lengthOfTimeRange", step.value()); + if (ret) + return ret; + return GRIB_SUCCESS; + } + else { + grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; + grib_handle* h = grib_handle_of_accessor(a); -// grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; -// grib_handle* h = grib_handle_of_accessor(a); + int err = 0; -// int err = 0; + long year; + long month; + long day; + long hour; + long minute; + long second; -// long year; -// long month; -// long day; -// long hour; -// long minute; -// long second; + 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; -// 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; + long coded_time_range, time_range, typeOfTimeIncrement; -// long coded_time_range, time_range, typeOfTimeIncrement; + double dend, dstep; -// double dend, dstep; + /*point in time */ + if (self->year == NULL) { + err = grib_set_long_internal(h, self->start_step, *val); + return err; + } -// [>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->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; -// 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; -// 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; + } -// 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; -// 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; -// 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; -// 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 ((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 (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; + } -// 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; + return GRIB_SUCCESS; + } } static int pack_string(grib_accessor* a, const char* val, size_t* len) { @@ -549,25 +556,17 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) { return GRIB_SUCCESS; } - -//static int unpack_string(grib_accessor* a, char* val, size_t* len) { -// throw std::runtime_error("g2end_step: unpack_string() is not implemented"); -// //return GRIB_NOT_IMPLEMENTED; -//} - 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; long unit; - ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit); - if (ret) + if ((ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit))) return ret; long value; - ret = grib_get_long_internal(h, "lengthOfTimeRange", &value); - if (ret) + if ((ret = grib_get_long_internal(h, "lengthOfTimeRange", &value))) return ret; Step step{(int) value, unit}; diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 8c8a35b23..3fe2efcb7 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -142,67 +142,105 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) //long start = 0, theEnd = 0; //ret = grib_get_long_internal(h, self->startStep, &start); - if (ret) - return ret; - long indicatorOfUnitOfTimeRange; - long forecastTime; - ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &indicatorOfUnitOfTimeRange); - if (ret) - return ret; - ret = grib_get_long_internal(h, "forecastTime", &forecastTime); - if (ret) - return ret; - - - size_t stepUnitsSize = 128; - char stepUnits[stepUnitsSize]; - ret = grib_get_string_internal(h, "stepUnits", stepUnits, &stepUnitsSize); - if (ret) - return ret; - //printf("stepUnits=%s\n", stepUnits); + // + // + // + // + //if (ret) + //return ret; size_t stepOutputFormatSize = 128; char stepOutputFormat[stepOutputFormatSize]; - ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize); - if (ret) + if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) return ret; - //printf("stepOutputFormat=%s\n", stepOutputFormat); - Step step_a{(int) forecastTime, indicatorOfUnitOfTimeRange}; - step_a.optimizeUnit(); - - if (strcmp(stepOutputFormat, "future") != 0) { - step_a.hide_hour_unit(); - } - - if (self->endStep == NULL) { - snprintf(buf, sizeof(buf), "%d%s", step_a.value(), step_a.unit_as_str().c_str()); - } - else { - long indicatorOfUnitForTimeRange; - long lengthOfTimeRange; - ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &indicatorOfUnitForTimeRange); + if (strcmp(stepOutputFormat, "future") == 0) { + long indicatorOfUnitOfTimeRange; + long forecastTime; + ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &indicatorOfUnitOfTimeRange); if (ret) return ret; - ret = grib_get_long_internal(h, "lengthOfTimeRange", &lengthOfTimeRange); + ret = grib_get_long_internal(h, "forecastTime", &forecastTime); if (ret) return ret; - Step length{(int) lengthOfTimeRange, indicatorOfUnitForTimeRange}; - Step step_b = step_a + length; - step_b.optimizeUnit(); - auto [a, b] = findCommonUnits(step_a, step_b); + + size_t stepUnitsSize = 128; + char stepUnits[stepUnitsSize]; + ret = grib_get_string_internal(h, "stepUnits", stepUnits, &stepUnitsSize); + if (ret) + return ret; + //printf("stepUnits=%s\n", stepUnits); + + size_t stepOutputFormatSize = 128; + char stepOutputFormat[stepOutputFormatSize]; + if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize) != GRIB_SUCCESS)) + return ret; + //printf("stepOutputFormat=%s\n", stepOutputFormat); + + Step step_a{(int) forecastTime, indicatorOfUnitOfTimeRange}; + step_a.optimizeUnit(); if (strcmp(stepOutputFormat, "future") != 0) { - step_b.hide_hour_unit(); - a.hide_hour_unit(); - b.hide_hour_unit(); + step_a.hide_hour_unit(); } - if (a.value() == 0) { - snprintf(buf, sizeof(buf), "0-%d%s", step_b.value(), step_b.unit_as_str().c_str()); + + if (self->endStep == NULL) { + snprintf(buf, sizeof(buf), "%d%s", step_a.value(), step_a.unit_as_str().c_str()); } else { - snprintf(buf, sizeof(buf), "%d-%d%s", a.value(), b.value(), step_b.unit_as_str().c_str()); + long indicatorOfUnitForTimeRange; + long lengthOfTimeRange; + ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &indicatorOfUnitForTimeRange); + if (ret) + return ret; + ret = grib_get_long_internal(h, "lengthOfTimeRange", &lengthOfTimeRange); + if (ret) + return ret; + + Step length{(int) lengthOfTimeRange, indicatorOfUnitForTimeRange}; + Step step_b = step_a + length; + step_b.optimizeUnit(); + auto [a, b] = findCommonUnits(step_a, step_b); + + if (strcmp(stepOutputFormat, "future") != 0) { + step_b.hide_hour_unit(); + a.hide_hour_unit(); + b.hide_hour_unit(); + } + if (a.value() == 0) { + snprintf(buf, sizeof(buf), "0-%d%s", step_b.value(), step_b.unit_as_str().c_str()); + } + else { + snprintf(buf, sizeof(buf), "%d-%d%s", a.value(), b.value(), b.unit_as_str().c_str()); + } + } + } + else { + grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; + grib_handle* h = grib_handle_of_accessor(a); + int ret = 0; + size_t size = 0; + long start = 0, theEnd = 0; + + ret = grib_get_long_internal(h, self->startStep, &start); + if (ret) + return ret; + + if (self->endStep == NULL) { + snprintf(buf, sizeof(buf), "%ld", start); + } + else { + ret = grib_get_long_internal(h, self->endStep, &theEnd); + if (ret) + return ret; + + if (start == theEnd) { + snprintf(buf, sizeof(buf), "%ld", theEnd); + } + else { + snprintf(buf, sizeof(buf), "%ld-%ld", start, theEnd); + } } } @@ -225,77 +263,61 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - std::vector steps = parse_range(val); - if (steps.size() == 0) { - return GRIB_INVALID_ARGUMENT; - } - //ret = grib_set_long_internal(h, self->startStep, steps[0].value()); - //if (ret) - // return ret; + size_t stepOutputFormatSize = 128; + char stepOutputFormat[stepOutputFormatSize]; + if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) + return ret; - //printf("val: %s\n", val); + 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_as_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 [a, b] = findCommonUnits(steps[0], steps[1]); - if (steps.size() == 1) { - //printf("unit_str 1: %s\n", steps[0].unit_as_str().c_str()); - steps[0].optimizeUnit(); - ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", steps[0].unit_as_long()); - if (ret) - return ret; + if ((ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", a.unit_as_long()))) + return ret; + if ((ret = grib_set_long_internal(h, "forecastTime", a.value()))) + return ret; - ret = grib_set_long_internal(h, "forecastTime", steps[0].value()); - if (ret) - return ret; - } - else if (steps.size() == 2) { - //ret = grib_set_long_internal(h, self->endStep, steps[1].value()); - //if (ret) - // return ret; - //printf("unit_str 2: %s\n", steps[1].unit_as_str().c_str()); - - steps[0].optimizeUnit(); - steps[1].optimizeUnit(); - auto [a, b] = findCommonUnits(steps[0], steps[1]); - - ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", a.unit_as_long()); - if (ret) - return ret; - ret = grib_set_long_internal(h, "forecastTime", a.value()); - if (ret) - return ret; - - - ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", b.unit_as_long()); - if (ret) - return ret; - ret = grib_set_long_internal(h, "lengthOfTimeRange", b.value()); - if (ret) - return ret; + if ((ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", b.unit_as_long()))) + return ret; + if ((ret = grib_set_long_internal(h, "lengthOfTimeRange", b.value()))) + return ret; + } + else { + std::string msg = std::string("Invalid range: ") + val; + throw std::runtime_error(msg); + } } else { - std::string msg = std::string("Invalid range: ") + val; - throw std::runtime_error(msg); + 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))) + return ret; + + if (self->endStep != NULL) { + if ((ret = grib_set_long_internal(h, self->endStep, theEnd))) + return ret; + } } - - //long start = 0, theEnd = -1; - //int ret = 0; - //char *p = NULL, *q = NULL; - - //start = strtol(val, &p, 10); - //theEnd = start; - - //if (*p != 0) - // theEnd = strtol(++p, &q, 10); - //ret = grib_set_long_internal(h, self->startStep, start); - //if (ret) - // return ret; - - //if (self->endStep != NULL) { - // ret = grib_set_long_internal(h, self->endStep, theEnd); - // if (ret) - // return ret; - //} - return 0; } diff --git a/src/grib_accessor_class_step_human_readable.cc b/src/grib_accessor_class_step_human_readable.cc index d9fe32d25..d83d71c8f 100644 --- a/src/grib_accessor_class_step_human_readable.cc +++ b/src/grib_accessor_class_step_human_readable.cc @@ -125,20 +125,52 @@ static int get_step_human_readable(grib_handle* h, char* result, size_t* length) size_t slen = 2; long step; - /* Change units to seconds (highest resolution) + //size_t stepOutputFormatSize = 128; + //char stepOutputFormat[stepOutputFormatSize]; + //if ((err = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) { + // printf("ERROR: unable to get stepOutputFormat stepOutputFormat=%s\n", stepOutputFormat); + // return err; + //} + + //if (strcmp(stepOutputFormat, "future") == 0) { + /* Change units to seconds (highest resolution) * before computing the step value */ - //err = grib_set_string(h, "stepUnits", "s", &slen); - //if (err) return err; - err = grib_get_long(h, "step", &step); - if (err) return err; + // //err = grib_set_string(h, "stepUnits", "s", &slen); + // //if (err) return err; + // err = grib_get_long(h, "step", &step); + // if (err) return err; - long indicator = grib_get_long(h, "indicatorOfUnitOfTimeRange", &indicator); - auto stepOptimizer = Step(step, indicator); - stepOptimizer.optimizeUnit(); + // long indicator = grib_get_long(h, "indicatorOfUnitOfTimeRange", &indicator); + // auto stepOptimizer = Step(step, indicator); + // stepOptimizer.optimizeUnit(); - snprintf(result, 1024, "%d%s", stepOptimizer.value(), stepOptimizer.unit_as_str().c_str()); + // snprintf(result, 1024, "%d%s", stepOptimizer.value(), stepOptimizer.unit_as_str().c_str()); + //} + //else { + long hour, minute, second; + /* Change units to seconds (highest resolution) + * before computing the step value + */ + err = grib_set_string(h, "stepUnits", "s", &slen); + if (err) return err; + err = grib_get_long(h, "step", &step); + if (err) return err; + + hour = step/3600; + minute = step/60 % 60; + second = step % 60; + /* sprintf(result, "%ld:%ld:%ld", hour, minute, second); */ + + if (second) { + snprintf(result, 1024, "%ldh %ldm %lds", hour, minute, second); + } else { + if (minute) snprintf(result, 1024, "%ldh %ldm", hour, minute); + else snprintf(result, 1024, "%ldh", hour); + } + + //} *length = strlen(result); return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 99d493bd5..a5ccbcba2 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -84,12 +84,12 @@ static grib_accessor_class _grib_accessor_class_step_in_units = { 0, /* is_missing */ &pack_long, /* pack_long */ &unpack_long, /* unpack_long */ - &pack_double, /* pack_double */ + 0, //&pack_double, /* pack_double */ 0, /* pack_float */ - &unpack_double, /* unpack_double */ + 0, //&unpack_double, /* unpack_double */ 0, /* unpack_float */ - &pack_string, /* pack_string */ - &unpack_string, /* unpack_string */ + 0, //&pack_string, /* pack_string */ + 0, //&unpack_string, /* unpack_string */ 0, /* pack_string_array */ 0, /* unpack_string_array */ 0, /* pack_bytes */ @@ -306,6 +306,11 @@ static int unpack_string(grib_accessor* a, 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) + return ret; + long unit; ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &unit); if (ret) @@ -317,7 +322,12 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) { return ret; Step step{(int) value, unit}; - sprintf(val, "%d%s", step.value(), step.unit_as_str().c_str()); + if (strcmp(stepOutputFormat, "future") == 0) { + sprintf(val, "%d%s", step.value(), step.unit_as_str().c_str()); + } + else { + sprintf(val, "%d", step.value()); + } return GRIB_SUCCESS; } diff --git a/src/step_optimizer.cc b/src/step_optimizer.cc index e65611712..76e27f19c 100644 --- a/src/step_optimizer.cc +++ b/src/step_optimizer.cc @@ -3,9 +3,27 @@ #include #include #include +#include +#include #include "step_optimizer.h" +std::vector> Step::unitOrder = { + {Unit::SECOND, 1}, + {Unit::MINUTE, 60}, + //{Unit::MINUTES15, 900}, + //{Unit::MINUTES30, 1800}, + {Unit::HOUR, 3600}, + //{Unit::HOURS3, 10800}, + //{Unit::HOURS6, 21600}, + //{Unit::HOURS12, 43200}, + {Unit::DAY, 86400}, + {Unit::MONTH, 2592000}, + //{Unit::YEAR, 31536000}, + //{Unit::YEARS10, 315360000}, + //{Unit::YEARS30, 946080000}, + //{Unit::CENTURY, 3153600000}, + }; std::string parse_step(std::string step) { if (step.find_first_of("smhdMYC") == std::string::npos) { @@ -103,15 +121,17 @@ Step& Step::optimizeUnit() { throw std::runtime_error(msg); } - for (auto it = unitMap_.end(); it != unitMap_.begin();) { - --it; + Seconds d = std::chrono::duration_cast(duration); + + for (auto it = unitOrder.rbegin(); it != unitOrder.rend(); ++it) { int multiplier = it->second; - if (duration.count() % multiplier == 0) { + if (d.count() % multiplier == 0) { value_ = duration.count() / multiplier; unit_ = it->first; return *this; } } + return *this; } @@ -240,7 +260,6 @@ Step operator+(const Step step1, const Step step2) { return Step(a.value_ + b.value_, a.unit_); } - std::pair findCommonUnits(Step startStep, Step endStep) { if (startStep.value_ == 0 || endStep.value_ == 0) { if (startStep.value_ == 0 && endStep.value_ == 0) { @@ -257,9 +276,14 @@ std::pair findCommonUnits(Step startStep, Step endStep) { return {startStep, endStep}; } - Unit unit = std::min(startStep.optimizeUnit().unit_, endStep.optimizeUnit().unit_); - startStep.setUnit(unit); - endStep.setUnit(unit); + auto it = std::find_if(Step::unitOrder.begin(), Step::unitOrder.end(), [&](const auto& e) { + return e.first == startStep.unit_ || e.first == endStep.unit_; + }); + + assert(it != Step::unitOrder.end()); + + startStep.setUnit(it->first); + endStep.setUnit(it->first); return {startStep, endStep}; } diff --git a/src/step_optimizer.h b/src/step_optimizer.h index 9b88fcd70..dc2a0ab56 100644 --- a/src/step_optimizer.h +++ b/src/step_optimizer.h @@ -177,22 +177,7 @@ private: long unit() const { return unit_; } Step& setUnit(Unit new_unit); Step(int value, Unit unit); - std::vector> unitMap_ = { - {Unit::SECOND, 1}, - {Unit::MINUTE, 60}, - //{Unit::MINUTES15, 900}, - //{Unit::MINUTES30, 1800}, - {Unit::HOUR, 3600}, - //{Unit::HOURS3, 10800}, - //{Unit::HOURS6, 21600}, - //{Unit::HOURS12, 43200}, - {Unit::DAY, 86400}, - {Unit::MONTH, 2592000}, - //{Unit::YEAR, 31536000}, - //{Unit::YEARS10, 315360000}, - //{Unit::YEARS30, 946080000}, - //{Unit::CENTURY, 3153600000}, - }; + static std::vector> unitOrder; int value_; Unit unit_; Unit default_unit_ = Unit::HOUR; diff --git a/tools/grib_dump.cc b/tools/grib_dump.cc index f61c6597e..941ac1879 100644 --- a/tools/grib_dump.cc +++ b/tools/grib_dump.cc @@ -1,4 +1,5 @@ /* + * iptio * (C) Copyright 2005- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 diff --git a/tools/grib_set.cc b/tools/grib_set.cc index a8e562a21..2cfc851aa 100644 --- a/tools/grib_set.cc +++ b/tools/grib_set.cc @@ -15,6 +15,7 @@ grib_option grib_options[] = { { "s:", 0, 0, 1, 1, 0 }, { "r", 0, 0, 0, 1, 0 }, { "d:", 0, 0, 0, 1, 0 }, + { "y", 0, 0, 0, 1, 0 }, /*{"n:","noise percentage","\n\t\tAdd noise to the data values. The noise added is the given percentage of the data value.\n",0,1,0},*/ { "p:", 0, 0, 1, 1, 0 }, { "P:", 0, 0, 0, 1, 0 }, diff --git a/tools/grib_tools.cc b/tools/grib_tools.cc index 3fc6eb708..a27af2ff8 100644 --- a/tools/grib_tools.cc +++ b/tools/grib_tools.cc @@ -1201,17 +1201,18 @@ void grib_print_key_values(grib_runtime_options* options, grib_handle* h) break; case GRIB_TYPE_LONG: ret = grib_get_long(h, options->print_keys[i].name, &lvalue); - if ( - (strcmp(options->print_keys[i].name, "indicatorOfUnitOfTimeRange") == 0) || - (strcmp(options->print_keys[i].name, "indicatorOfUnitForTimeRange") == 0) - ) - { - snprintf(value, 32, "%s", StepUnitsTable::to_str(lvalue).c_str()); - } - else - { + //if ( + // (strcmp(options->print_keys[i].name, "indicatorOfUnitOfTimeRange") == 0) || + // (strcmp(options->print_keys[i].name, "indicatorOfUnitForTimeRange") == 0) && + // (strcmp(options->step_output_format, "future") == 0) + //) + //{ + // snprintf(value, 32, "%s", StepUnitsTable::to_str(lvalue).c_str()); + //} + //else + //{ snprintf(value, 32, "%ld", lvalue); - } + //} break; case GRIB_TYPE_BYTES: ret = grib_get_string(h, options->print_keys[i].name, value, &len); From b38d7386dc01743543d40e916c9e78b36a7f8cfb Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 17 Aug 2023 14:30:06 +0000 Subject: [PATCH 013/125] ECC-1620: CTest + bug fixes --- src/grib_accessor_class_g2end_step.cc | 120 ++--- src/grib_accessor_class_g2step_range.cc | 129 +++--- src/grib_accessor_class_step_in_units.cc | 184 +++----- src/step_optimizer.cc | 282 +----------- src/step_optimizer.h | 552 ++++++++++++++++------- tests/CMakeLists.txt | 1 + tests/grib_ecc-1620.sh | 211 +++++++++ tools/grib_get.cc | 1 + 8 files changed, 834 insertions(+), 646 deletions(-) create mode 100755 tests/grib_ecc-1620.sh diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index e79a87562..6d695d5df 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -118,8 +118,8 @@ static grib_accessor_class _grib_accessor_class_g2end_step = { 0, /* pack_float */ 0, //&unpack_double, /* unpack_double */ 0, /* unpack_float */ - 0, //&pack_string, /* pack_string */ - 0, //&unpack_string, /* unpack_string */ + &pack_string, /* pack_string */ + &unpack_string, /* unpack_string */ 0, /* pack_string_array */ 0, /* unpack_string_array */ 0, /* pack_bytes */ @@ -420,8 +420,8 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return ret; if (strcmp(stepOutputFormat, "future") == 0) { - Step step{(int) *val, StepUnitsTable::to_long("h")}; - ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit_as_long()); + Step step{*val, "h"}; + ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit().to_long()); if (ret) return ret; @@ -543,9 +543,9 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - Step step = Step(parse_step(std::string(val))); + Step step = Step(parse_step(std::string(val))); - ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit_as_long()); + ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit().to_long()); if (ret) return ret; @@ -557,57 +557,79 @@ static int pack_string(grib_accessor* a, const 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_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - long unit; - if ((ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit))) + size_t stepOutputFormatSize = 128; + char stepOutputFormat[stepOutputFormatSize]; + if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) return ret; - long value; - if ((ret = grib_get_long_internal(h, "lengthOfTimeRange", &value))) + /* point in time */ + if (self->year == NULL) { + long value; + if ((ret = grib_get_long_internal(h, self->start_step, &value))) + return ret; + long unit; + if ((ret = grib_get_long_internal(h, self->unit, &unit))) + return ret; + + Step start_step = Step(value, unit); + if (strcmp(stepOutputFormat, "future") == 0) { + start_step.optimizeUnit(); + snprintf(val, *len, "%ld%s", start_step.value(), start_step.unit().to_string().c_str()); + } + else { + snprintf(val, *len, "%ld", start_step.value()); + } + return 0; + } + + + long numberOfTimeRange; + Assert(self->numberOfTimeRange); + if ((ret = grib_get_long_internal(h, self->numberOfTimeRange, &numberOfTimeRange))) return ret; + Assert(numberOfTimeRange == 1 || numberOfTimeRange == 2); - Step step{(int) value, unit}; + if (numberOfTimeRange == 1) { + long unit; + long value; - sprintf(val, "%d%s", step.value(), step.unit_as_str().c_str()); + if ((ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit))) + return ret; + if ((ret = grib_get_long_internal(h, "lengthOfTimeRange", &value))) + return ret; + + Step start_step{value, unit}; + start_step.hide_hour_unit(); + start_step.optimizeUnit(); + + if ((ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &unit)) != GRIB_SUCCESS) + return ret; + if ((ret = grib_get_long_internal(h, "forecastTime", &value)) != GRIB_SUCCESS) + return ret; + + Step step{value, unit}; + Step end_step = start_step + step; + end_step.optimizeUnit(); + end_step.hide_hour_unit(); + + if (strcmp(stepOutputFormat, "future") == 0) { + snprintf(val, *len, "%ld%s", end_step.value(), end_step.unit().to_string().c_str()); + } + else { + snprintf(val, *len, "%ld", end_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 unit; - ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit); - if (ret) - return ret; - - - long stepUnits; - ret = grib_get_long_internal(h, "stepUnits", &stepUnits); - if (ret) - return ret; - - Step step; - if (stepUnits != 255) { - step = Step((int) *val, stepUnits); - } - else { - step = Step((int) *val, unit); - } - - ret = grib_set_long_internal(h, "lengthOfTimeRange", step.value()); - if (ret) - return ret; - ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", step.unit_as_long()); - if (ret) - return ret; - - return ret; + // not implemented + return GRIB_NOT_IMPLEMENTED; } static int unpack_double(grib_accessor* a, double* val, size_t* len) { @@ -630,14 +652,8 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) { if (ret) return ret; - if (stepUnits != 255) { - Step step = Step(value, unit); - *val = step.getDoubleValue(stepUnits); - } - else { - Step step = Step(value, unit); - *val = step.value(); - } + Step step = Step(value, unit); + *val = step.setUnit(stepUnits).value(); return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 3fe2efcb7..9e3f14bbc 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -139,15 +139,6 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) char buf[100]; int ret = 0; size_t size = 0; - //long start = 0, theEnd = 0; - - //ret = grib_get_long_internal(h, self->startStep, &start); - // - // - // - // - //if (ret) - //return ret; size_t stepOutputFormatSize = 128; char stepOutputFormat[stepOutputFormatSize]; @@ -156,37 +147,24 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) if (strcmp(stepOutputFormat, "future") == 0) { long indicatorOfUnitOfTimeRange; - long forecastTime; - ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &indicatorOfUnitOfTimeRange); - if (ret) - return ret; - ret = grib_get_long_internal(h, "forecastTime", &forecastTime); - if (ret) + if ((ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &indicatorOfUnitOfTimeRange)) != GRIB_SUCCESS) return ret; + long forecastTime; + if ((ret = grib_get_long_internal(h, "forecastTime", &forecastTime)) != GRIB_SUCCESS) + return ret; size_t stepUnitsSize = 128; char stepUnits[stepUnitsSize]; - ret = grib_get_string_internal(h, "stepUnits", stepUnits, &stepUnitsSize); - if (ret) + if ((ret = grib_get_string_internal(h, "stepUnits", stepUnits, &stepUnitsSize)) != GRIB_SUCCESS) return ret; - //printf("stepUnits=%s\n", stepUnits); - size_t stepOutputFormatSize = 128; - char stepOutputFormat[stepOutputFormatSize]; - if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize) != GRIB_SUCCESS)) - return ret; - //printf("stepOutputFormat=%s\n", stepOutputFormat); - - Step step_a{(int) forecastTime, indicatorOfUnitOfTimeRange}; + Step step_a{forecastTime, indicatorOfUnitOfTimeRange}; step_a.optimizeUnit(); - - if (strcmp(stepOutputFormat, "future") != 0) { - step_a.hide_hour_unit(); - } + step_a.hide_hour_unit(); if (self->endStep == NULL) { - snprintf(buf, sizeof(buf), "%d%s", step_a.value(), step_a.unit_as_str().c_str()); + snprintf(buf, sizeof(buf), "%ld%s", step_a.value(), step_a.unit().to_string().c_str()); } else { long indicatorOfUnitForTimeRange; @@ -198,21 +176,20 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) if (ret) return ret; - Step length{(int) lengthOfTimeRange, indicatorOfUnitForTimeRange}; - Step step_b = step_a + length; + Step length{lengthOfTimeRange, indicatorOfUnitForTimeRange}; + Step step_b = step_a + length; step_b.optimizeUnit(); auto [a, b] = findCommonUnits(step_a, step_b); - if (strcmp(stepOutputFormat, "future") != 0) { - step_b.hide_hour_unit(); - a.hide_hour_unit(); - b.hide_hour_unit(); - } + step_b.hide_hour_unit(); + a.hide_hour_unit(); + b.hide_hour_unit(); + if (a.value() == 0) { - snprintf(buf, sizeof(buf), "0-%d%s", step_b.value(), step_b.unit_as_str().c_str()); + snprintf(buf, sizeof(buf), "0%s-%ld%s", step_b.unit().to_string().c_str(), step_b.value(), step_b.unit().to_string().c_str()); } else { - snprintf(buf, sizeof(buf), "%d-%d%s", a.value(), b.value(), b.unit_as_str().c_str()); + snprintf(buf, sizeof(buf), "%ld%s-%ld%s", a.value(), a.unit().to_string().c_str(), b.value(), b.unit().to_string().c_str()); } } } @@ -231,8 +208,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) snprintf(buf, sizeof(buf), "%ld", start); } else { - ret = grib_get_long_internal(h, self->endStep, &theEnd); - if (ret) + if ((ret = grib_get_long_internal(h, self->endStep, &theEnd)) != GRIB_SUCCESS) return ret; if (start == theEnd) { @@ -269,13 +245,13 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) return ret; if (strcmp(stepOutputFormat, "future") == 0) { - std::vector steps = parse_range(val); + 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_as_long()))) + 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; @@ -283,16 +259,16 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) else if (steps.size() == 2) { steps[0].optimizeUnit(); steps[1].optimizeUnit(); - auto [a, b] = findCommonUnits(steps[0], steps[1]); + auto [s0, s1] = findCommonUnits(steps[0], steps[1]); - if ((ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", a.unit_as_long()))) + if ((ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", s0.unit().to_long()))) return ret; - if ((ret = grib_set_long_internal(h, "forecastTime", a.value()))) + if ((ret = grib_set_long_internal(h, "forecastTime", s0.value()))) return ret; - if ((ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", b.unit_as_long()))) + if ((ret = grib_set_long_internal(h, "indicatorOfUnitForTimeRange", s1.unit().to_long()))) return ret; - if ((ret = grib_set_long_internal(h, "lengthOfTimeRange", b.value()))) + if ((ret = grib_set_long_internal(h, "lengthOfTimeRange", s1.value()))) return ret; } else { @@ -343,23 +319,54 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) static int unpack_long(grib_accessor* a, long* val, size_t* len) { - char buff[100]; - size_t bufflen = 100; - long start, theEnd; - char* p = buff; - char* q = NULL; - int err = 0; + grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; + 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) + return ret; - if ((err = unpack_string(a, buff, &bufflen)) != GRIB_SUCCESS) - return err; + if (strcmp(stepOutputFormat, "future") == 0) { + long unit = 0; + long value = 0; - start = strtol(buff, &p, 10); - theEnd = start; - if (*p != 0) - theEnd = strtol(++p, &q, 10); + if ((ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &unit)) != GRIB_SUCCESS) + return ret; + if ((ret = grib_get_long_internal(h, "forecastTime", &value)) != GRIB_SUCCESS) + return ret; + Step start_step(value, unit); + Step step = start_step; - *val = theEnd; + if (self->endStep != NULL) { + if ((ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit)) != GRIB_SUCCESS) + return ret; + if ((ret = grib_get_long_internal(h, "lengthOfTimeRange", &value)) != GRIB_SUCCESS) + return ret; + Step end_step(value, unit); + step = start_step + end_step; + } + + step.optimizeUnit(); + *val = step.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; + + start = strtol(buff, &p, 10); + theEnd = start; + if (*p != 0) + theEnd = strtol(++p, &q, 10); + + *val = theEnd; + } return 0; } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index a5ccbcba2..fbf8b6634 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -88,8 +88,8 @@ static grib_accessor_class _grib_accessor_class_step_in_units = { 0, /* pack_float */ 0, //&unpack_double, /* unpack_double */ 0, /* unpack_float */ - 0, //&pack_string, /* pack_string */ - 0, //&unpack_string, /* unpack_string */ + &pack_string, /* pack_string */ + &unpack_string, /* unpack_string */ 0, /* pack_string_array */ 0, /* unpack_string_array */ 0, /* pack_bytes */ @@ -219,69 +219,69 @@ 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{(int) *val, StepUnitsTable::to_long("h")}; - ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", step.unit_as_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; - //long indicatorOfUnitForTimeRange, lengthOfTimeRange; + //grib_handle* h = grib_handle_of_accessor(a); + //int ret = 0; - //if ((err = grib_get_long_internal(h, self->codedUnits, &codedUnits))) - // return err; - //if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits))) - // return err; + //Step step{*val, "h"}; + //ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", step.unit().to_long()); + //if (ret) + // return ret; - //unpack_long(a, &oldStep, len); + //ret = grib_set_long_internal(h, "forecastTime", step.value()); + //if (ret) + // return ret; + //return GRIB_SUCCESS; - //if (stepUnits != codedUnits) { - // codedStep = *val * u2s[stepUnits]; - // if (codedStep % u2s2[codedUnits] != 0) { - // codedUnits = stepUnits; - // err = grib_set_long_internal(h, self->codedUnits, codedUnits); - // if (err != GRIB_SUCCESS) - // return err; - // codedStep = *val; - // } - // else { - // codedStep = codedStep / u2s2[codedUnits]; - // } - //} - //else { - // codedStep = *val; - //} + 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; + long indicatorOfUnitForTimeRange, lengthOfTimeRange; - //if (self->indicatorOfUnitForTimeRange) { - // if ((err = grib_get_long_internal(h, - // self->indicatorOfUnitForTimeRange, &indicatorOfUnitForTimeRange))) - // return err; - // if ((err = grib_get_long_internal(h, - // self->lengthOfTimeRange, &lengthOfTimeRange))) - // return err; - // if (codedUnits == indicatorOfUnitForTimeRange) - // lengthOfTimeRange -= codedStep - oldStep; - // else - // lengthOfTimeRange -= codedStep * u2s2[codedUnits] / u2s2[indicatorOfUnitForTimeRange]; - // lengthOfTimeRange = lengthOfTimeRange > 0 ? lengthOfTimeRange : 0; - // err = grib_set_long_internal(grib_handle_of_accessor(a), self->lengthOfTimeRange, lengthOfTimeRange); - // if (err != GRIB_SUCCESS) - // return err; - //} + if ((err = grib_get_long_internal(h, self->codedUnits, &codedUnits))) + return err; + if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits))) + return err; - //return grib_set_long_internal(grib_handle_of_accessor(a), self->codedStep, codedStep); + unpack_long(a, &oldStep, len); + + if (stepUnits != codedUnits) { + codedStep = *val * u2s[stepUnits]; + if (codedStep % u2s2[codedUnits] != 0) { + codedUnits = stepUnits; + err = grib_set_long_internal(h, self->codedUnits, codedUnits); + if (err != GRIB_SUCCESS) + return err; + codedStep = *val; + } + else { + codedStep = codedStep / u2s2[codedUnits]; + } + } + else { + codedStep = *val; + } + + if (self->indicatorOfUnitForTimeRange) { + if ((err = grib_get_long_internal(h, + self->indicatorOfUnitForTimeRange, &indicatorOfUnitForTimeRange))) + return err; + if ((err = grib_get_long_internal(h, + self->lengthOfTimeRange, &lengthOfTimeRange))) + return err; + if (codedUnits == indicatorOfUnitForTimeRange) + lengthOfTimeRange -= codedStep - oldStep; + else + lengthOfTimeRange -= codedStep * u2s2[codedUnits] / u2s2[indicatorOfUnitForTimeRange]; + lengthOfTimeRange = lengthOfTimeRange > 0 ? lengthOfTimeRange : 0; + err = grib_set_long_internal(grib_handle_of_accessor(a), self->lengthOfTimeRange, lengthOfTimeRange); + if (err != GRIB_SUCCESS) + return err; + } + + 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) { @@ -289,12 +289,12 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) { 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, "indicatorOfUnitOfTimeRange", step.unit_as_long()); + Step step = Step(parse_step(std::string(val))); + ret = grib_set_long_internal(h, self->codedUnits, step.unit().to_long()); if (ret) return ret; - ret = grib_set_long_internal(h, "forecastTime", step.value()); + ret = grib_set_long_internal(h, self->codedStep, step.value()); if (ret) return ret; @@ -312,21 +312,21 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) { return ret; long unit; - ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &unit); - if (ret) + if ((ret = grib_get_long_internal(h, self->codedUnits, &unit)) != GRIB_SUCCESS) return ret; long value; - ret = grib_get_long_internal(h, "forecastTime", &value); - if (ret) + if ((ret = grib_get_long_internal(h, self->codedStep, &value)) != GRIB_SUCCESS) return ret; - Step step{(int) value, unit}; + Step step{value, unit}; + step.optimizeUnit(); if (strcmp(stepOutputFormat, "future") == 0) { - sprintf(val, "%d%s", step.value(), step.unit_as_str().c_str()); + step.hide_hour_unit(); + snprintf(val, *len, "%ld%s", step.value(), step.unit().to_string().c_str()); } else { - sprintf(val, "%d", step.value()); + snprintf(val, *len, "%ld", step.value()); } return GRIB_SUCCESS; @@ -334,37 +334,7 @@ static int unpack_string(grib_accessor* a, char* 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, "indicatorOfUnitOfTimeRange", &unit); - if (ret) - return ret; - - - long stepUnits; - ret = grib_get_long_internal(h, self->stepUnits, &stepUnits); - if (ret) - return ret; - - Step step; - if (stepUnits != 255) { - step = Step((int) *val, stepUnits); - } - else { - step = Step((int) *val, unit); - } - - ret = grib_set_long_internal(h, "forecastTime", step.value()); - if (ret) - return ret; - ret = grib_set_long_internal(h, "indicatorOfUnitOfTimeRange", step.unit_as_long()); - if (ret) - return ret; - - return ret; + return GRIB_NOT_IMPLEMENTED; } @@ -374,12 +344,12 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) { int ret = 0; long unit; - ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &unit); + ret = grib_get_long_internal(h, self->codedUnits, &unit); if (ret) return ret; long value; - ret = grib_get_long_internal(h, "forecastTime", &value); + ret = grib_get_long_internal(h, self->codedStep, &value); if (ret) return ret; @@ -388,14 +358,8 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) { if (ret) return ret; - if (stepUnits != 255) { - Step step = Step(value, unit); - *val = step.getDoubleValue(stepUnits); - } - else { - Step step = Step(value, unit); - *val = step.value(); - } + Step step{(double) value, unit}; + *val = step.setUnit(stepUnits).value(); return GRIB_SUCCESS; } diff --git a/src/step_optimizer.cc b/src/step_optimizer.cc index 76e27f19c..eca3df57f 100644 --- a/src/step_optimizer.cc +++ b/src/step_optimizer.cc @@ -8,22 +8,8 @@ #include "step_optimizer.h" -std::vector> Step::unitOrder = { - {Unit::SECOND, 1}, - {Unit::MINUTE, 60}, - //{Unit::MINUTES15, 900}, - //{Unit::MINUTES30, 1800}, - {Unit::HOUR, 3600}, - //{Unit::HOURS3, 10800}, - //{Unit::HOURS6, 21600}, - //{Unit::HOURS12, 43200}, - {Unit::DAY, 86400}, - {Unit::MONTH, 2592000}, - //{Unit::YEAR, 31536000}, - //{Unit::YEARS10, 315360000}, - //{Unit::YEARS30, 946080000}, - //{Unit::CENTURY, 3153600000}, - }; + + std::string parse_step(std::string step) { if (step.find_first_of("smhdMYC") == std::string::npos) { @@ -33,257 +19,33 @@ std::string parse_step(std::string step) { } -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)); +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) { + Step::Unit unit = a.unit_ > b.unit_ ? a.unit_ : b.unit_; + a.setUnit(unit); + b.setUnit(unit); } - prev = pos + 1; - } - std::string token = parse_step(range_str.substr(prev)); - if (token.size() > 0) { - steps.push_back(Step(token)); - } - return steps; -} - - -std::string Step::unit_as_str() const { - if ((unit_ == Unit::HOUR) && hide_hour_unit_) - return std::string(""); - else - return StepUnitsTable::to_str(unit_); -} - -long Step::unit_as_long() const { - return unit_; -} - -Step::Step(int value, long 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."); - } - - value_ = value; - unit_ = StepUnitsTable::to_unit(unit); -} - -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_ = StepUnitsTable::to_unit(u_str); -} - -Step::Step(int value, Unit 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; -} - -Step& Step::optimizeUnit() { - if (value_ == 0) { - return *this; - } - - Seconds duration(0); - switch (unit_) { - 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: " + StepUnitsTable::to_str(unit_); - throw std::runtime_error(msg); - } - - Seconds d = std::chrono::duration_cast(duration); - - for (auto it = unitOrder.rbegin(); it != unitOrder.rend(); ++it) { - int multiplier = it->second; - if (d.count() % multiplier == 0) { - value_ = duration.count() / multiplier; - unit_ = it->first; - return *this; + else if (a.value_ == 0) { + a.setUnit(b.unit_); } - } - - return *this; -} - -Step& Step::setUnit(std::string new_unit) { - setUnit(StepUnitsTable::to_unit(new_unit)); - return *this; -} - -Step& Step::setUnit(long new_unit) { - setUnit(StepUnitsTable::to_unit(new_unit)); - return *this; -} - -Step& Step::setUnit(Unit new_unit) { - if (value_ == 0) { - unit_ = new_unit; - return *this; - } - if (unit_ == new_unit) { - return *this; - } - Seconds duration(0); - switch (unit_) { - 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: " + std::to_string(static_cast(unit_)); - throw std::runtime_error(msg); - } - - switch (new_unit) { - case Unit::SECOND: - value_ = duration.count(); - break; - case Unit::MINUTE: - value_ = std::chrono::duration_cast(duration).count(); - break; - case Unit::HOUR: - value_ = std::chrono::duration_cast(duration).count(); - break; - case Unit::DAY: - value_ = std::chrono::duration_cast(duration).count(); - break; - case Unit::MONTH: - value_ = std::chrono::duration_cast(duration).count(); - break; - default: - std::string msg = "Unknown unit: " + std::to_string(static_cast(new_unit)); - throw std::runtime_error(msg); - } - unit_ = new_unit; - - return *this; -} - -double Step::getDoubleValue(long new_unit) const { - Seconds duration(0); - switch (unit_) { - 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: " + std::to_string(static_cast(unit_)); - throw std::runtime_error(msg); - } - - double value; - switch (new_unit) { - case Unit::SECOND: - value = std::chrono::duration_cast(duration).count(); - break; - case Unit::MINUTE: - value = std::chrono::duration_cast(duration).count(); - break; - case Unit::HOUR: - value = std::chrono::duration_cast(duration).count(); - break; - case Unit::DAY: - value = std::chrono::duration_cast(duration).count(); - break; - case Unit::MONTH: - value = std::chrono::duration_cast(duration).count(); - break; - default: - std::string msg = "Unknown unit: " + std::to_string(static_cast(new_unit)); - throw std::runtime_error(msg); - } - - return value; -} - -bool Step::operator==(const Step& other) const { - if (value_ == other.value_ && unit_ == other.unit_) { - return true; - } - return false; -} - -Step operator+(const Step step1, const Step step2) { - auto [a, b] = findCommonUnits(step1, step2); - return Step(a.value_ + b.value_, a.unit_); -} - -std::pair findCommonUnits(Step startStep, Step endStep) { - if (startStep.value_ == 0 || endStep.value_ == 0) { - if (startStep.value_ == 0 && endStep.value_ == 0) { - Unit unit = StepUnitsTable::unit_duration(startStep.unit_) > StepUnitsTable::unit_duration(endStep.unit_) ? startStep.unit_ : endStep.unit_; - startStep.setUnit(unit); - endStep.setUnit(unit); + else if (b.value_ == 0) { + b.setUnit(a.unit_); } - else if (startStep.value_ == 0) { - startStep.setUnit(endStep.unit_); - } - else if (endStep.value_ == 0) { - endStep.setUnit(startStep.unit_); - } - return {startStep, endStep}; + return {a, b}; } - auto it = std::find_if(Step::unitOrder.begin(), Step::unitOrder.end(), [&](const auto& e) { - return e.first == startStep.unit_ || e.first == endStep.unit_; + auto it = std::find_if(Step::Unit::unitOrder.begin(), Step::Unit::unitOrder.end(), [&](const auto& e) { + return e == a.unit().to_value() || e == b.unit().to_value(); }); - assert(it != Step::unitOrder.end()); + assert(it != Step::Unit::unitOrder.end()); - startStep.setUnit(it->first); - endStep.setUnit(it->first); + a.setUnit(*it); + b.setUnit(*it); - return {startStep, endStep}; + return {a, b}; } diff --git a/src/step_optimizer.h b/src/step_optimizer.h index dc2a0ab56..db6fe0bbd 100644 --- a/src/step_optimizer.h +++ b/src/step_optimizer.h @@ -8,182 +8,408 @@ #include #include #include +#include +#include +#include +#include -enum Unit : long { - MINUTE = 0, - HOUR = 1, - DAY = 2, - MONTH = 3, - YEAR = 4, - YEARS10 = 5, - YEARS30 = 6, - CENTURY = 7, - HOURS3 = 10, - HOURS6 = 11, - HOURS12 = 12, - SECOND = 13, - MINUTES15 = 14, - MINUTES30 = 15, - MISSING = 255, -}; - -using Minutes = std::chrono::duration>; -using Hours = std::chrono::duration>; -using Days = std::chrono::duration>; -using Months = std::chrono::duration>; -using Years = std::chrono::duration>; -using Years10 = std::chrono::duration>; -using Years30 = std::chrono::duration>; -using Centuries = std::chrono::duration>; -using Hours3 = std::chrono::duration>; -using Hours6 = std::chrono::duration>; -using Hours12 = std::chrono::duration>; -using Seconds = std::chrono::duration>; -using Minutes15 = std::chrono::duration>; -using Minutes30 = std::chrono::duration>; -using Missing = std::chrono::duration>; - -using MinutesDouble = std::chrono::duration>; -using HoursDouble = std::chrono::duration>; -using DaysDouble = std::chrono::duration>; -using MonthsDouble = std::chrono::duration>; -using YearsDouble = std::chrono::duration>; -using Years10Double = std::chrono::duration>; -using Years30Double = std::chrono::duration>; -using CenturiesDouble = std::chrono::duration>; -using Hours3Double = std::chrono::duration>; -using Hours6Double = std::chrono::duration>; -using Hours12Double = std::chrono::duration>; -using SecondsDouble = std::chrono::duration>; -using Minutes15Double = std::chrono::duration>; -using Minutes30Double = std::chrono::duration>; -using MissingDouble = std::chrono::duration>; - -class StepUnitsTable{ -private: - StepUnitsTable() { - } -public: - static Unit to_unit(const std::string& str) { - static std::map map = { - {"m", Unit::MINUTE}, - {"h", Unit::HOUR}, - {"d", Unit::DAY}, - {"M", Unit::MONTH}, - {"Y", Unit::YEAR}, - {"10Y", Unit::YEARS10}, - {"30Y", Unit::YEARS30}, - {"C", Unit::CENTURY}, - {"3h", Unit::HOURS3}, - {"6h", Unit::HOURS6}, - {"12h", Unit::HOURS12}, - {"s", Unit::SECOND}, - {"15m", Unit::MINUTES15}, - {"30m", Unit::MINUTES30}, - {"255", Unit::MISSING}, - }; - return map[str]; - } - - static long to_long(const std::string& str) { - return to_unit(str); - } - - static Unit to_unit(long code) { - static std::map map = { - {Unit::MINUTE, Unit::MINUTE}, - {Unit::HOUR, Unit::HOUR}, - {Unit::DAY, Unit::DAY}, - {Unit::MONTH, Unit::MONTH}, - {Unit::YEAR, Unit::YEAR}, - {Unit::YEARS10, Unit::YEARS10}, - {Unit::YEARS30, Unit::YEARS30}, - {Unit::CENTURY, Unit::CENTURY}, - {Unit::HOURS3, Unit::HOURS3}, - {Unit::HOURS6, Unit::HOURS6}, - {Unit::HOURS12, Unit::HOURS12}, - {Unit::SECOND, Unit::SECOND}, - {Unit::MINUTES15, Unit::MINUTES15}, - {Unit::MINUTES30, Unit::MINUTES30}, - {Unit::MISSING, Unit::MISSING}, - }; - return map[code]; - } - - static std::string to_str(long code) { - static std::map map = { - {Unit::MINUTE, "m"}, - {Unit::HOUR, "h"}, - {Unit::DAY, "d"}, - {Unit::MONTH, "M"}, - {Unit::YEAR, "Y"}, - {Unit::YEARS10, "10Y"}, - {Unit::YEARS30, "30Y"}, - {Unit::CENTURY, "C"}, - {Unit::HOURS3, "3h"}, - {Unit::HOURS6, "6h"}, - {Unit::HOURS12, "12h"}, - {Unit::SECOND, "s"}, - {Unit::MINUTES15, "15m"}, - {Unit::MINUTES30, "30m"}, - {Unit::MISSING, "255"}, - }; - return map[code]; - } - - static double unit_duration(long code) { - static std::map map = { - {Unit::MINUTE, Minutes::period::num / Minutes::period::den}, - {Unit::HOUR, Hours::period::num / Hours::period::den}, - {Unit::DAY, Days::period::num / Days::period::den}, - {Unit::MONTH, Months::period::num / Months::period::den}, - {Unit::YEAR, Years::period::num / Years::period::den}, - {Unit::YEARS10, Years10::period::num / Years10::period::den}, - {Unit::YEARS30, Years30::period::num / Years30::period::den}, - {Unit::CENTURY, Centuries::period::num / Centuries::period::den}, - {Unit::HOURS3, Hours3::period::num / Hours3::period::den}, - {Unit::HOURS6, Hours6::period::num / Hours6::period::den}, - {Unit::HOURS12, Hours12::period::num / Hours12::period::den}, - {Unit::SECOND, Seconds::period::num / Seconds::period::den}, - {Unit::MINUTES15, Minutes15::period::num / Minutes15::period::den}, - {Unit::MINUTES30, Minutes30::period::num / Minutes30::period::den}, - }; - return map[code]; - } -}; +template using Minutes = std::chrono::duration>; +template using Hours = std::chrono::duration>; +template using Days = std::chrono::duration>; +template using Months = std::chrono::duration>; +template using Years = std::chrono::duration>; +template using Years10 = std::chrono::duration>; +template using Years30 = std::chrono::duration>; +template using Centuries = std::chrono::duration>; +template using Hours3 = std::chrono::duration>; +template using Hours6 = std::chrono::duration>; +template using Hours12 = std::chrono::duration>; +template using Seconds = std::chrono::duration>; +template using Minutes15 = std::chrono::duration>; +template using Minutes30 = std::chrono::duration>; +template using Missing = std::chrono::duration>; +template class Step { public: + class Unit { + public: + enum class Value { + MINUTE = 0, + HOUR = 1, + DAY = 2, + MONTH = 3, + YEAR = 4, + YEARS10 = 5, + YEARS30 = 6, + CENTURY = 7, + HOURS3 = 10, + HOURS6 = 11, + HOURS12 = 12, + SECOND = 13, + MINUTES15 = 14, + MINUTES30 = 15, + MISSING = 255, + }; + + + explicit Unit() : value_(Value::HOUR) {} + explicit Unit(Value unit_value) : value_(unit_value) {} + + explicit Unit(const std::string& unit_value) { + value_ = map_.name_to_unit(unit_value); + } + + explicit Unit(long unit_value) { + value_ = map_.long_to_unit(unit_value); + } + + bool operator>(const Unit& other) const {return map_.unit_to_duration(value_) > map_.unit_to_duration(other.value_);} + bool operator==(const Value value) const {return map_.unit_to_duration(value_) == map_.unit_to_duration(value);} + Unit& operator=(const Value value) { + value_ = value; + return *this; + } + + std::string to_string() const { + if ((value_ == Value::HOUR) && hide_hour_unit_) { + return ""; + } + else { + return map_.unit_to_name(value_); + } + } + long to_long() const {return map_.unit_to_long(value_);} + Value to_value() const {return value_;} + void hide_hour_unit() { + hide_hour_unit_ = true; + } + + static std::vector unitOrder; + + private: + bool hide_hour_unit_ = false; + class Map { + public: + Map() { + for (const auto& entry : tab_) { + // unit_value <-> unit_name + name_to_value_[entry.unit_name] = entry.unit_value; + value_to_name_[entry.unit_value] = entry.unit_name; + + // unit_value <-> duration in seconds + value_to_duration_[entry.unit_value] = entry.duration; + duration_to_value_[entry.duration] = entry.unit_value; + + // unit_value <-> wmo_code + value_to_long_[entry.unit_value] = static_cast(entry.unit_value); + long_to_value_[static_cast(entry.unit_value)] = entry.unit_value; + } + } + + // wmo_code <-> unit_name + std::string unit_to_name(const Value& unit_value) const {return value_to_name_.at(unit_value);} + Value name_to_unit(const std::string& name) const {return name_to_value_.at(name);} + + // unit_value <-> duration + long unit_to_duration(const Value& unit_value) const {return value_to_duration_.at(unit_value);} + Value duration_to_unit(long duration) const {return duration_to_value_.at(duration);} + + // wmo_code <-> unit_name + long unit_to_long(const Value& unit_value) const {return value_to_long_.at(unit_value);} + Value long_to_unit(long wmo_code) const {return long_to_value_.at(wmo_code);} + + private: + struct Entry { + Unit::Value unit_value; + std::string unit_name; + long duration; + }; + + const std::array tab_ = { + Entry{Value::MISSING , "MISSING" , 0}, + Entry{Value::SECOND , "s" , 1}, + Entry{Value::MINUTE , "m" , 60}, + Entry{Value::MINUTES15 , "15m" , 900}, + Entry{Value::MINUTES30 , "30m" , 1800}, + Entry{Value::HOUR , "h" , 3600}, + Entry{Value::HOURS3 , "3h" , 10800}, + Entry{Value::HOURS6 , "6h" , 21600}, + Entry{Value::HOURS12 , "12h" , 43200}, + Entry{Value::DAY , "D" , 86400}, + Entry{Value::MONTH , "M" , 2592000}, + Entry{Value::YEAR , "Y" , 31536000}, + Entry{Value::YEARS10 , "10Y" , 315360000}, + Entry{Value::YEARS30 , "30Y" , 946080000}, + Entry{Value::CENTURY , "C" , 3153600000}, + }; + + std::unordered_map name_to_value_; + std::unordered_map value_to_name_; + + std::unordered_map value_to_long_; + std::unordered_map long_to_value_; + + std::unordered_map value_to_duration_; + std::unordered_map duration_to_value_; + }; + + + Value value_; + static Map map_; + public: + static Map& get_converter() {return map_;} + }; + + // Constructors Step() : value_(0), unit_(Unit::SECOND) {} - Step(int value, long unit); + Step(T value, const Unit& unit); + Step(T value, long unit); + Step(T value, const std::string& unit); explicit Step(const std::string& str); - int value() const { return value_; } - std::string unit_as_str() const; - long unit_as_long() const; - void hide_hour_unit() { hide_hour_unit_ = true; } + // Getters + T value() const { return value_; } + Unit unit() const { return unit_; } - Step& optimizeUnit(); - Step& setUnit(std::string new_unit); - Step& setUnit(long new_unit); - double getDoubleValue(long unit) const; - bool operator==(const Step& other) const; - friend std::pair findCommonUnits(Step startStep, Step endStep); - friend Step operator+(const Step step1, const Step step2); + // Setters + Step& setUnit(long new_unit); + Step& setUnit(const std::string& new_unit); + Step& setUnit(const Step::Unit& new_unit); + Step& setUnit(const typename Step::Unit::Value new_unit); + + // Operators + bool operator==(const Step& other) const; + 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();} private: - long unit() const { return unit_; } - Step& setUnit(Unit new_unit); - Step(int value, Unit unit); - static std::vector> unitOrder; - int value_; + T value_; Unit unit_; - Unit default_unit_ = Unit::HOUR; - bool hide_hour_unit_ = false; }; -std::pair findCommonUnits(Step, Step); + +template +//typename Step::Unit::Map Step::Unit::map_ = Step::Unit::Map(); +typename Step::Unit::Map Step::Unit::map_{}; + + +template +std::vector::Unit::Value> Step::Unit::unitOrder = { + Value::SECOND, + Value::MINUTE, + //{StepValue::MINUTES15, 900}, + //{StepValue::MINUTES30, 1800}, + Value::HOUR, + //{StepValue::HOURS3, 10800}, + //{StepValue::HOURS6, 21600}, + //{StepValue::HOURS12, 43200}, + //Value::DAY, + //Value::MONTH, + //{StepValue::YEAR, 31536000}, + //{StepValue::YEARS10, 315360000}, + //{StepValue::YEARS30, 946080000}, + //{StepValue::CENTURY, 3153600000}, + }; + + std::string parse_step(std::string step); -std::vector parse_range(const std::string& range_str); + +template +bool Step::operator==(const Step& other) const { + if (value_ == other.value_ && unit_ == other.unit_) { + return true; + } + 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, long unit) : value_{value}, unit_{Unit{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_{Unit{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_ = Unit{u_str}; +} + +template +Step::Step(T value, const Unit& 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::Value::SECOND: + duration = Seconds(value_); + break; + case Unit::Value::MINUTE: + duration = Minutes(value_); + break; + case Unit::Value::HOUR: + duration = Hours(value_); + break; + case Unit::Value::DAY: + duration = Days(value_); + break; + case Unit::Value::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 = Unit::unitOrder.rbegin(); it != Unit::unitOrder.rend(); ++it) { + long multiplier = Unit::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(Unit{unit_name}); + return *this; +} + +template +Step& Step::setUnit(long unit_code) { + setUnit(Unit{unit_code}); + return *this; +} + +template +Step& Step::setUnit(const Step::Unit& new_unit) { + setUnit(new_unit.to_value()); + return *this; +} + + +template +Step& Step::setUnit(const typename Step::Unit::Value new_unit) { + if (value_ == 0) { + unit_ = new_unit; + return *this; + } + if (unit_ == new_unit) { + return *this; + } + Seconds duration(0); + switch (unit_.to_value()) { + case Unit::Value::SECOND: + duration = Seconds(value_); + break; + case Unit::Value::MINUTE: + duration = Minutes(value_); + break; + case Unit::Value::HOUR: + duration = Hours(value_); + break; + case Unit::Value::DAY: + duration = Days(value_); + break; + case Unit::Value::MONTH: + duration = Months(value_); + break; + default: + std::string msg = "Unknown unit: " + unit_.to_string(); + throw std::runtime_error(msg); + } + + switch (new_unit) { + case Unit::Value::SECOND: + value_ = duration.count(); + break; + case Unit::Value::MINUTE: + value_ = std::chrono::duration_cast>(duration).count(); + break; + case Unit::Value::HOUR: + value_ = std::chrono::duration_cast>(duration).count(); + break; + case Unit::Value::DAY: + value_ = std::chrono::duration_cast>(duration).count(); + break; + case Unit::Value::MONTH: + value_ = std::chrono::duration_cast>(duration).count(); + break; + default: + std::string msg = "Unknown unit: " + Step::Unit{new_unit}.to_string(); + throw std::runtime_error(msg); + } + unit_ = new_unit; + + return *this; +} + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f8c25d935..59999dd0b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -215,6 +215,7 @@ if( HAVE_BUILD_TOOLS ) grib_ecc-1397 grib_ecc-1425 grib_ecc-1467 + grib_ecc-1620 grib_set_bytes grib_set_force bufr_ecc-556 diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh new file mode 100755 index 000000000..14d13ebaa --- /dev/null +++ b/tests/grib_ecc-1620.sh @@ -0,0 +1,211 @@ +#!/bin/sh +# (C) Copyright 2005- ECMWF. +# +# This software is licensed under the terms of the Apache Licence Version 2.0 +# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. +# +# In applying this licence, ECMWF does not waive the privileges and immunities granted to it by +# virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. +# + +. ./include.ctest.sh + +grib_check_key_equals() +{ + a_file=$1 + a_params=$2 + a_expected=$3 + a_result=`${tools_dir}/grib_get $a_params $a_file` + if [ "$a_result" != "$a_expected" ]; then + echo "File: '$a_file'" + echo "Key(s): '$a_params'" + echo "Expected: '$a_expected'" + echo "Result: '$a_result'" + exit 1 + fi +} + +label="grib_ecc-1620" +temp=temp.$label + + +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=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=59,indicatorOfUnitOfTimeRange=m $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "59 m" +grib_check_key_equals $temp "-p $keys__" "59" +grib_check_key_equals $temp "-y -p $keys__" "59" +grib_check_key_equals $temp "-p $keys_s" "59" +grib_check_key_equals $temp "-y -p $keys_s" "59m" +grib_check_key_equals $temp "-p $keys_i" "59" +grib_check_key_equals $temp "-y -p $keys_i" "59" +grib_check_key_equals $temp "-p $keys_d" "59" +grib_check_key_equals $temp "-y -p $keys_d" "59" + +${tools_dir}/grib_set -s forecastTime=60,indicatorOfUnitOfTimeRange=m $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "60 m" +grib_check_key_equals $temp "-p $keys__" "1" +grib_check_key_equals $temp "-y -p $keys__" "1" +grib_check_key_equals $temp "-p $keys_s" "1" +grib_check_key_equals $temp "-y -p $keys_s" "1" +grib_check_key_equals $temp "-p $keys_i" "1" +grib_check_key_equals $temp "-y -p $keys_i" "1" +grib_check_key_equals $temp "-p $keys_d" "1" +grib_check_key_equals $temp "-y -p $keys_d" "1" + +${tools_dir}/grib_set -s forecastTime=61,indicatorOfUnitOfTimeRange=m $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "61 m" +grib_check_key_equals $temp "-p $keys__" "61" +grib_check_key_equals $temp "-y -p $keys__" "61" +grib_check_key_equals $temp "-p $keys_s" "61" +grib_check_key_equals $temp "-y -p $keys_s" "61m" +grib_check_key_equals $temp "-p $keys_i" "61" +grib_check_key_equals $temp "-y -p $keys_i" "61" +grib_check_key_equals $temp "-p $keys_d" "61" +grib_check_key_equals $temp "-y -p $keys_d" "61" + +#grib_check_key_equals $temp "-y -s stepUnits=h -p $keys__" "1.0166666666666666" +#grib_check_key_equals $temp "-y -s stepUnits=h -p $keys_s" "1.0166666666666666" +#grib_check_key_equals $temp "-y -s stepUnits=h -p $keys_i" "1" +#grib_check_key_equals $temp "-y -s stepUnits=h -p $keys_d" "1.0166666666666666" + +${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "24 h" +grib_check_key_equals $temp "-p $keys__" "24" +grib_check_key_equals $temp "-y -p $keys__" "24" +grib_check_key_equals $temp "-p $keys_s" "24" +grib_check_key_equals $temp "-y -p $keys_s" "24" +grib_check_key_equals $temp "-p $keys_i" "24" +grib_check_key_equals $temp "-y -p $keys_i" "24" +grib_check_key_equals $temp "-p $keys_d" "24" +grib_check_key_equals $temp "-y -p $keys_d" "24" + +${tools_dir}/grib_set -s forecastTime=1440,indicatorOfUnitOfTimeRange=m $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "1440 m" +grib_check_key_equals $temp "-p $keys__" "24" +grib_check_key_equals $temp "-y -p $keys__" "24" +grib_check_key_equals $temp "-p $keys_s" "24" +grib_check_key_equals $temp "-y -p $keys_s" "24" +grib_check_key_equals $temp "-p $keys_i" "24" +grib_check_key_equals $temp "-y -p $keys_i" "24" +grib_check_key_equals $temp "-p $keys_d" "24" +grib_check_key_equals $temp "-y -p $keys_d" "24" + + + +fn="${data_dir}/reduced_gaussian_sub_area.grib2" +low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" +keys__="stepRange,startStep,endStep" +keys_s="stepRange:s,startStep:s,endStep:s" +keys_i="stepRange:i,startStep:i,endStep:i" +keys_d="stepRange:d,startStep:d,endStep:d" + +${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=2,indicatorOfUnitForTimeRange=h $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 m 2 h" +grib_check_key_equals $temp "-p $keys__" "0-2 0 2" +grib_check_key_equals $temp "-y -p $keys__" "0-2 0 2" +grib_check_key_equals $temp "-p $keys_s" "0-2 0 2" +grib_check_key_equals $temp "-y -p $keys_s" "0-2 0m 2" +grib_check_key_equals $temp "-p $keys_i" "2 0 2" +grib_check_key_equals $temp "-y -p $keys_i" "2 0 2" +grib_check_key_equals $temp "-p $keys_d" "2 0 2" +grib_check_key_equals $temp "-y -p $keys_d" "2 0 2" + +${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" +grib_check_key_equals $temp "-p $keys__" "24-48 24 48" +grib_check_key_equals $temp "-y -p $keys__" "24-48 24 48" +grib_check_key_equals $temp "-p $keys_s" "24-48 24 48" +grib_check_key_equals $temp "-y -p $keys_s" "24-48 24 48" +grib_check_key_equals $temp "-p $keys_i" "48 24 48" +grib_check_key_equals $temp "-y -p $keys_i" "48 24 48" +grib_check_key_equals $temp "-p $keys_d" "48 24 48" +grib_check_key_equals $temp "-y -p $keys_d" "48 24 48" + +${tools_dir}/grib_set -s forecastTime=25,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=1,indicatorOfUnitForTimeRange=D $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "25 h 1 D" +grib_check_key_equals $temp "-p $keys__" "25-49 25 49" +grib_check_key_equals $temp "-y -p $keys__" "25-49 25 49" +grib_check_key_equals $temp "-p $keys_s" "25-49 25 49" +grib_check_key_equals $temp "-y -p $keys_s" "25-49 25 49" +grib_check_key_equals $temp "-p $keys_i" "49 25 49" +grib_check_key_equals $temp "-y -p $keys_i" "49 25 49" +grib_check_key_equals $temp "-p $keys_d" "49 25 49" +grib_check_key_equals $temp "-y -p $keys_d" "49 25 49" + +${tools_dir}/grib_set -s forecastTime=45,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=15,indicatorOfUnitForTimeRange=m $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "45 m 15 m" +grib_check_key_equals $temp "-p $keys__" "45-60 45 60" +grib_check_key_equals $temp "-y -p $keys__" "45m-60m 45 60" +grib_check_key_equals $temp "-p $keys_s" "45-60 45 1" +grib_check_key_equals $temp "-y -p $keys_s" "45m-60m 45m 1" +grib_check_key_equals $temp "-p $keys_i" "60 45 60" +grib_check_key_equals $temp "-y -p $keys_i" "1 45 60" +grib_check_key_equals $temp "-p $keys_d" "60 45 60" +grib_check_key_equals $temp "-y -p $keys_d" "1 45 60" + +${tools_dir}/grib_set -s forecastTime=60,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=2,indicatorOfUnitForTimeRange=h $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "60 m 2 h" +grib_check_key_equals $temp "-p $keys__" "1-3 1 3" +grib_check_key_equals $temp "-y -p $keys__" "1-3 1 3" +grib_check_key_equals $temp "-p $keys_s" "1-3 1 3" +grib_check_key_equals $temp "-y -p $keys_s" "1-3 1 3" +grib_check_key_equals $temp "-p $keys_i" "3 1 3" +grib_check_key_equals $temp "-y -p $keys_i" "3 1 3" +grib_check_key_equals $temp "-p $keys_d" "3 1 3" +grib_check_key_equals $temp "-y -p $keys_d" "3 1 3" + +${tools_dir}/grib_set -s forecastTime=18,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=6,indicatorOfUnitForTimeRange=h $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "18 h 6 h" +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" +grib_check_key_equals $temp "-y -p $keys_i" "24 18 24" +grib_check_key_equals $temp "-p $keys_d" "24 18 24" +grib_check_key_equals $temp "-y -p $keys_d" "24 18 24" + +${tools_dir}/grib_set -s forecastTime=1080,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=360,indicatorOfUnitForTimeRange=m $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "1080 m 360 m" +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" +grib_check_key_equals $temp "-y -p $keys_i" "24 18 24" +grib_check_key_equals $temp "-p $keys_d" "24 18 24" +grib_check_key_equals $temp "-y -p $keys_d" "24 18 24" + +${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" +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" +grib_check_key_equals $temp "-y -p $keys_i" "24 18 24" +grib_check_key_equals $temp "-p $keys_d" "24 18 24" +grib_check_key_equals $temp "-y -p $keys_d" "24 18 24" + +rm -f $temp + + + diff --git a/tools/grib_get.cc b/tools/grib_get.cc index 4d5040bfa..74a366b7d 100644 --- a/tools/grib_get.cc +++ b/tools/grib_get.cc @@ -15,6 +15,7 @@ grib_option grib_options[] = { { "f", 0, 0, 0, 1, 0 }, { "p:", 0, 0, 0, 1, 0 }, { "F:", 0, 0, 1, 1, "%g" }, + { "y", 0, 0, 0, 1, 0 }, { "B:", 0, 0, 0, 1, 0 }, { "l:", 0, 0, 0, 1, 0 }, { "P:", 0, 0, 0, 1, 0 }, From 3b7eb7c02ffb6eee111fcc66d15b5a0c4f00bd46 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 18 Aug 2023 15:53:12 +0000 Subject: [PATCH 014/125] ECC-1620: Step utility functions --- src/CMakeLists.txt | 3 +- src/grib_accessor_class_g2end_step.cc | 71 ++---------- src/grib_accessor_class_g2step_range.cc | 109 +++++------------- ...grib_accessor_class_step_human_readable.cc | 2 +- src/grib_accessor_class_step_in_units.cc | 33 +++--- src/{step_optimizer.cc => step.cc} | 2 +- src/{step_optimizer.h => step.h} | 5 +- src/step_utilities.cc | 42 +++++++ src/step_utilities.h | 12 ++ tools/grib_tools.cc | 2 +- 10 files changed, 117 insertions(+), 164 deletions(-) rename src/{step_optimizer.cc => step.cc} (97%) rename src/{step_optimizer.h => step.h} (98%) create mode 100644 src/step_utilities.cc create mode 100644 src/step_utilities.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2adbef70a..69f39a820 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,7 +9,8 @@ # nor does it submit to any jurisdiction. # list( APPEND eccodes_src_files - step_optimizer.cc + step.cc + step_utilities.cc grib_api.h grib_timer.cc eccodes.h diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 9ea691772..e43de49aa 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -9,7 +9,8 @@ */ #include "grib_api_internal.h" -#include "step_optimizer.h" +#include "step.h" +#include "step_utilities.h" #include /* @@ -561,69 +562,17 @@ static int unpack_string(grib_accessor* a, 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) - return ret; + 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(); - /* point in time */ - if (self->year == NULL) { - long value; - if ((ret = grib_get_long_internal(h, self->start_step, &value))) - return ret; - long unit; - if ((ret = grib_get_long_internal(h, self->unit, &unit))) - return ret; - - Step start_step = Step(value, unit); - if (strcmp(stepOutputFormat, "future") == 0) { - start_step.optimizeUnit(); - snprintf(val, *len, "%ld%s", start_step.value(), start_step.unit().to_string().c_str()); - } - else { - snprintf(val, *len, "%ld", start_step.value()); - } - return 0; + if (futureOutputEnabled(h)) { + snprintf(val, *len, "%ld%s", step_b.value(), step_b.unit().to_string().c_str()); } - - - long numberOfTimeRange; - Assert(self->numberOfTimeRange); - if ((ret = grib_get_long_internal(h, self->numberOfTimeRange, &numberOfTimeRange))) - return ret; - Assert(numberOfTimeRange == 1 || numberOfTimeRange == 2); - - if (numberOfTimeRange == 1) { - long unit; - long value; - - if ((ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit))) - return ret; - if ((ret = grib_get_long_internal(h, "lengthOfTimeRange", &value))) - return ret; - - Step start_step{value, unit}; - start_step.hide_hour_unit(); - start_step.optimizeUnit(); - - if ((ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &unit)) != GRIB_SUCCESS) - return ret; - if ((ret = grib_get_long_internal(h, "forecastTime", &value)) != GRIB_SUCCESS) - return ret; - - Step step{value, unit}; - Step end_step = start_step + step; - end_step.optimizeUnit(); - end_step.hide_hour_unit(); - - if (strcmp(stepOutputFormat, "future") == 0) { - snprintf(val, *len, "%ld%s", end_step.value(), end_step.unit().to_string().c_str()); - } - else { - snprintf(val, *len, "%ld", end_step.value()); - } + else { + snprintf(val, *len, "%ld", step_b.value()); } - return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 9e3f14bbc..6d685a356 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -13,7 +13,8 @@ *******************************************/ #include "grib_api_internal.h" -#include "step_optimizer.h" +#include "step.h" +#include "step_utilities.h" #include /* This is used by make_class.pl @@ -146,58 +147,18 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; if (strcmp(stepOutputFormat, "future") == 0) { - long indicatorOfUnitOfTimeRange; - if ((ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &indicatorOfUnitOfTimeRange)) != GRIB_SUCCESS) - return ret; - - long forecastTime; - if ((ret = grib_get_long_internal(h, "forecastTime", &forecastTime)) != GRIB_SUCCESS) - return ret; - - size_t stepUnitsSize = 128; - char stepUnits[stepUnitsSize]; - if ((ret = grib_get_string_internal(h, "stepUnits", stepUnits, &stepUnitsSize)) != GRIB_SUCCESS) - return ret; - - Step step_a{forecastTime, indicatorOfUnitOfTimeRange}; - step_a.optimizeUnit(); + auto [forcastTime, lengthOfTimeRange] = getTimeRange(h); + auto [step_a, step_b] = findCommonUnits(forcastTime.optimizeUnit(), lengthOfTimeRange.optimizeUnit()); step_a.hide_hour_unit(); - - if (self->endStep == NULL) { + step_b.hide_hour_unit(); + if (step_a == step_b) { snprintf(buf, sizeof(buf), "%ld%s", step_a.value(), step_a.unit().to_string().c_str()); } else { - long indicatorOfUnitForTimeRange; - long lengthOfTimeRange; - ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &indicatorOfUnitForTimeRange); - if (ret) - return ret; - ret = grib_get_long_internal(h, "lengthOfTimeRange", &lengthOfTimeRange); - if (ret) - return ret; - - Step length{lengthOfTimeRange, indicatorOfUnitForTimeRange}; - Step step_b = step_a + length; - step_b.optimizeUnit(); - auto [a, b] = findCommonUnits(step_a, step_b); - - step_b.hide_hour_unit(); - a.hide_hour_unit(); - b.hide_hour_unit(); - - if (a.value() == 0) { - snprintf(buf, sizeof(buf), "0%s-%ld%s", step_b.unit().to_string().c_str(), step_b.value(), step_b.unit().to_string().c_str()); - } - else { - snprintf(buf, sizeof(buf), "%ld%s-%ld%s", a.value(), a.unit().to_string().c_str(), b.value(), b.unit().to_string().c_str()); - } + 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()); } } else { - grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; - grib_handle* h = grib_handle_of_accessor(a); - int ret = 0; - size_t size = 0; long start = 0, theEnd = 0; ret = grib_get_long_internal(h, self->startStep, &start); @@ -328,45 +289,27 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) return ret; - if (strcmp(stepOutputFormat, "future") == 0) { - long unit = 0; - long value = 0; + //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; - if ((ret = grib_get_long_internal(h, "indicatorOfUnitOfTimeRange", &unit)) != GRIB_SUCCESS) - return ret; - if ((ret = grib_get_long_internal(h, "forecastTime", &value)) != GRIB_SUCCESS) - return ret; - Step start_step(value, unit); - Step step = start_step; + // start = strtol(buff, &p, 10); + // theEnd = start; + // if (*p != 0) + // theEnd = strtol(++p, &q, 10); - if (self->endStep != NULL) { - if ((ret = grib_get_long_internal(h, "indicatorOfUnitForTimeRange", &unit)) != GRIB_SUCCESS) - return ret; - if ((ret = grib_get_long_internal(h, "lengthOfTimeRange", &value)) != GRIB_SUCCESS) - return ret; - Step end_step(value, unit); - step = start_step + end_step; - } - - step.optimizeUnit(); - *val = step.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; - - start = strtol(buff, &p, 10); - theEnd = start; - if (*p != 0) - theEnd = strtol(++p, &q, 10); - - *val = theEnd; - } + // *val = theEnd; + //} return 0; } diff --git a/src/grib_accessor_class_step_human_readable.cc b/src/grib_accessor_class_step_human_readable.cc index d83d71c8f..ebd2c4a7b 100644 --- a/src/grib_accessor_class_step_human_readable.cc +++ b/src/grib_accessor_class_step_human_readable.cc @@ -9,7 +9,7 @@ */ #include "grib_api_internal.h" -#include "step_optimizer.h" +#include "step.h" /* This is used by make_class.pl diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index fbf8b6634..8323cfdd4 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -9,7 +9,8 @@ */ #include "grib_api_internal.h" -#include "step_optimizer.h" +#include "step.h" +#include "step_utilities.h" #include /* This is used by make_class.pl @@ -306,22 +307,26 @@ static int unpack_string(grib_accessor* a, 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) - return ret; + //size_t stepOutputFormatSize = 128; + //char stepOutputFormat[stepOutputFormatSize]; + //if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) + // return ret; - long unit; - if ((ret = grib_get_long_internal(h, self->codedUnits, &unit)) != GRIB_SUCCESS) - return ret; + //long unit; + //if ((ret = grib_get_long_internal(h, self->codedUnits, &unit)) != GRIB_SUCCESS) + // return ret; - long value; - if ((ret = grib_get_long_internal(h, self->codedStep, &value)) != GRIB_SUCCESS) - return ret; + //long value; + //if ((ret = grib_get_long_internal(h, self->codedStep, &value)) != GRIB_SUCCESS) + // return ret; - Step step{value, unit}; - step.optimizeUnit(); - if (strcmp(stepOutputFormat, "future") == 0) { + //Step step{value, unit}; + //step.optimizeUnit(); + + auto [forcastTime, lengthOfTimeRange] = getTimeRange(h); + auto [step, step_b] = findCommonUnits(forcastTime.optimizeUnit(), lengthOfTimeRange.optimizeUnit()); + + if (futureOutputEnabled(h)) { step.hide_hour_unit(); snprintf(val, *len, "%ld%s", step.value(), step.unit().to_string().c_str()); } diff --git a/src/step_optimizer.cc b/src/step.cc similarity index 97% rename from src/step_optimizer.cc rename to src/step.cc index eca3df57f..b353a38fb 100644 --- a/src/step_optimizer.cc +++ b/src/step.cc @@ -6,7 +6,7 @@ #include #include -#include "step_optimizer.h" +#include "step.h" diff --git a/src/step_optimizer.h b/src/step.h similarity index 98% rename from src/step_optimizer.h rename to src/step.h index db6fe0bbd..f819002e5 100644 --- a/src/step_optimizer.h +++ b/src/step.h @@ -68,6 +68,7 @@ public: bool operator>(const Unit& other) const {return map_.unit_to_duration(value_) > map_.unit_to_duration(other.value_);} bool operator==(const Value value) const {return map_.unit_to_duration(value_) == map_.unit_to_duration(value);} + bool operator==(const Unit& unit) const {return map_.unit_to_duration(value_) == map_.unit_to_duration(unit.value_);} Unit& operator=(const Value value) { value_ = value; return *this; @@ -164,7 +165,7 @@ public: }; // Constructors - Step() : value_(0), unit_(Unit::SECOND) {} + Step() : value_(0), unit_(Unit::Value::SECOND) {} Step(T value, const Unit& unit); Step(T value, long unit); Step(T value, const std::string& unit); @@ -223,7 +224,7 @@ std::string parse_step(std::string step); template bool Step::operator==(const Step& other) const { - if (value_ == other.value_ && unit_ == other.unit_) { + if ((value_ == other.value_) && (unit_ == other.unit_)) { return true; } return false; diff --git a/src/step_utilities.cc b/src/step_utilities.cc new file mode 100644 index 000000000..19c5cacbd --- /dev/null +++ b/src/step_utilities.cc @@ -0,0 +1,42 @@ +#include "step_utilities.h" + + +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) + return {}; + + long value = 0; + if (grib_get_long_internal(h, value_key.c_str(), &value) != GRIB_SUCCESS) + return {}; + + return Step(value, unit); + } + else { + return {}; + } +} + +std::optional> getForecastTime(grib_handle* h) { + return getStep(h, "forecastTime", "indicatorOfUnitOfTimeRange"); +} + +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())}; +} + +bool futureOutputEnabled(grib_handle* h) { + int ret = 0; + size_t stepOutputFormatSize = 128; + char stepOutputFormat[stepOutputFormatSize]; + 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 new file mode 100644 index 000000000..2ac9e3e49 --- /dev/null +++ b/src/step_utilities.h @@ -0,0 +1,12 @@ +#pragma once + +#include "grib_api_internal.h" +#include "step.h" + +#include + +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); +bool futureOutputEnabled(grib_handle* h); diff --git a/tools/grib_tools.cc b/tools/grib_tools.cc index a27af2ff8..7b008ad3f 100644 --- a/tools/grib_tools.cc +++ b/tools/grib_tools.cc @@ -9,7 +9,7 @@ */ #include "grib_tools.h" -#include "step_optimizer.h" +//#include "step_optimizer.h" #include #if HAVE_LIBJASPER From bf4e481cd6034c77f4bb55db43f4f24e0704ec18 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 23 Aug 2023 01:08:51 +0000 Subject: [PATCH 015/125] ECC-1620: More step utilities --- src/grib_accessor_class_g2step_range.cc | 20 +- src/grib_accessor_class_step_in_units.cc | 29 +- src/step.cc | 13 +- src/step.h | 353 +++++++++++------------ src/step_utilities.cc | 5 + src/step_utilities.h | 32 ++ tests/grib_ecc-1620.sh | 91 ++++-- 7 files changed, 308 insertions(+), 235 deletions(-) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 6d685a356..a3ff5a0bb 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -141,21 +141,19 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) int ret = 0; size_t size = 0; - size_t stepOutputFormatSize = 128; - char stepOutputFormat[stepOutputFormatSize]; - if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) - return ret; + if (futureOutputEnabled(h)) { + Step step_a; + Step step_b; + if ((ret = getOptTimeRange(h, step_a, step_b)) != GRIB_SUCCESS) + return ret; - if (strcmp(stepOutputFormat, "future") == 0) { - auto [forcastTime, lengthOfTimeRange] = getTimeRange(h); - auto [step_a, step_b] = findCommonUnits(forcastTime.optimizeUnit(), lengthOfTimeRange.optimizeUnit()); - step_a.hide_hour_unit(); - step_b.hide_hour_unit(); 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), "%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()); } 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), "%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()); } } else { diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 8323cfdd4..b8b27d0bb 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -306,32 +306,19 @@ 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) + return ret; - //size_t stepOutputFormatSize = 128; - //char stepOutputFormat[stepOutputFormatSize]; - //if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) - // return ret; - - //long unit; - //if ((ret = grib_get_long_internal(h, self->codedUnits, &unit)) != GRIB_SUCCESS) - // return ret; - - //long value; - //if ((ret = grib_get_long_internal(h, self->codedStep, &value)) != GRIB_SUCCESS) - // return ret; - - //Step step{value, unit}; - //step.optimizeUnit(); - - auto [forcastTime, lengthOfTimeRange] = getTimeRange(h); - auto [step, step_b] = findCommonUnits(forcastTime.optimizeUnit(), lengthOfTimeRange.optimizeUnit()); + snprintf(val, *len, "%f%s", step_a.value(), step_a.unit().to_string().c_str()); if (futureOutputEnabled(h)) { - step.hide_hour_unit(); - snprintf(val, *len, "%ld%s", step.value(), step.unit().to_string().c_str()); + snprintf(val, *len, "%f%s", step_a.value(), step_a.unit().to_string().c_str()); } else { - snprintf(val, *len, "%ld", step.value()); + snprintf(val, *len, "%f", step_a.value()); } return GRIB_SUCCESS; diff --git a/src/step.cc b/src/step.cc index b353a38fb..4aa810a08 100644 --- a/src/step.cc +++ b/src/step.cc @@ -9,6 +9,13 @@ #include "step.h" +UnitType::Map UnitType::map_{}; + +std::vector UnitType::unitOrder = { + Unit::SECOND, + Unit::MINUTE, + Unit::HOUR, + }; std::string parse_step(std::string step) { @@ -25,7 +32,7 @@ std::pair, Step> findCommonUnits(const Step& startStep, c if (a.value_ == 0 || b.value_ == 0) { if (a.value_ == 0 && b.value_ == 0) { - Step::Unit unit = a.unit_ > b.unit_ ? a.unit_ : b.unit_; + UnitType unit = a.unit_ > b.unit_ ? a.unit_ : b.unit_; a.setUnit(unit); b.setUnit(unit); } @@ -38,11 +45,11 @@ std::pair, Step> findCommonUnits(const Step& startStep, c return {a, b}; } - auto it = std::find_if(Step::Unit::unitOrder.begin(), Step::Unit::unitOrder.end(), [&](const auto& e) { + 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(); }); - assert(it != Step::Unit::unitOrder.end()); + assert(it != UnitType::unitOrder.end()); a.setUnit(*it); b.setUnit(*it); diff --git a/src/step.h b/src/step.h index f819002e5..45514441d 100644 --- a/src/step.h +++ b/src/step.h @@ -31,193 +31,171 @@ template using Minutes30 = std::chrono::duration using Missing = std::chrono::duration>; +enum class Unit { + MINUTE = 0, + HOUR = 1, + DAY = 2, + MONTH = 3, + YEAR = 4, + YEARS10 = 5, + YEARS30 = 6, + CENTURY = 7, + HOURS3 = 10, + HOURS6 = 11, + HOURS12 = 12, + SECOND = 13, + MINUTES15 = 14, + MINUTES30 = 15, + MISSING = 255, +}; + + +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);} + + 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; + return *this; + } + + std::string to_string() const { + if ((value_ == Unit::HOUR) && hide_hour_unit_) { + return ""; + } + else { + return map_.unit_to_name(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;} + static std::vector unitOrder; + +private: + bool hide_hour_unit_ = false; + class Map { + public: + Map() { + for (const auto& entry : tab_) { + // unit_value <-> unit_name + name_to_value_[entry.unit_name] = entry.unit_value; + value_to_name_[entry.unit_value] = entry.unit_name; + + // unit_value <-> duration in seconds + value_to_duration_[entry.unit_value] = entry.duration; + duration_to_value_[entry.duration] = entry.unit_value; + + // unit_value <-> wmo_code + value_to_long_[entry.unit_value] = static_cast(entry.unit_value); + long_to_value_[static_cast(entry.unit_value)] = entry.unit_value; + } + } + + // wmo_code <-> unit_name + std::string unit_to_name(const Unit& unit_value) const {return value_to_name_.at(unit_value);} + Unit name_to_unit(const std::string& name) const {return name_to_value_.at(name);} + + // unit_value <-> duration + long unit_to_duration(const Unit& unit_value) const {return value_to_duration_.at(unit_value);} + Unit duration_to_unit(long duration) const {return duration_to_value_.at(duration);} + + // wmo_code <-> unit_name + long unit_to_long(const Unit& unit_value) const {return value_to_long_.at(unit_value);} + Unit long_to_unit(long wmo_code) const {return long_to_value_.at(wmo_code);} + + private: + struct Entry { + Unit unit_value; + std::string unit_name; + long duration; + }; + + const std::array tab_ = { + Entry{Unit::MISSING , "MISSING" , 0}, + Entry{Unit::SECOND , "s" , 1}, + Entry{Unit::MINUTE , "m" , 60}, + Entry{Unit::MINUTES15 , "15m" , 900}, + Entry{Unit::MINUTES30 , "30m" , 1800}, + Entry{Unit::HOUR , "h" , 3600}, + Entry{Unit::HOURS3 , "3h" , 10800}, + Entry{Unit::HOURS6 , "6h" , 21600}, + Entry{Unit::HOURS12 , "12h" , 43200}, + Entry{Unit::DAY , "D" , 86400}, + Entry{Unit::MONTH , "M" , 2592000}, + Entry{Unit::YEAR , "Y" , 31536000}, + Entry{Unit::YEARS10 , "10Y" , 315360000}, + Entry{Unit::YEARS30 , "30Y" , 946080000}, + Entry{Unit::CENTURY , "C" , 3153600000}, + }; + + std::unordered_map name_to_value_; + std::unordered_map value_to_name_; + + std::unordered_map value_to_long_; + std::unordered_map long_to_value_; + + std::unordered_map value_to_duration_; + std::unordered_map duration_to_value_; + }; + + + Unit value_; + static Map map_; +public: + static Map& get_converter() {return map_;} +}; + + + + + template class Step { public: - class Unit { - public: - enum class Value { - MINUTE = 0, - HOUR = 1, - DAY = 2, - MONTH = 3, - YEAR = 4, - YEARS10 = 5, - YEARS30 = 6, - CENTURY = 7, - HOURS3 = 10, - HOURS6 = 11, - HOURS12 = 12, - SECOND = 13, - MINUTES15 = 14, - MINUTES30 = 15, - MISSING = 255, - }; - - - explicit Unit() : value_(Value::HOUR) {} - explicit Unit(Value unit_value) : value_(unit_value) {} - - explicit Unit(const std::string& unit_value) { - value_ = map_.name_to_unit(unit_value); - } - - explicit Unit(long unit_value) { - value_ = map_.long_to_unit(unit_value); - } - - bool operator>(const Unit& other) const {return map_.unit_to_duration(value_) > map_.unit_to_duration(other.value_);} - bool operator==(const Value value) const {return map_.unit_to_duration(value_) == map_.unit_to_duration(value);} - bool operator==(const Unit& unit) const {return map_.unit_to_duration(value_) == map_.unit_to_duration(unit.value_);} - Unit& operator=(const Value value) { - value_ = value; - return *this; - } - - std::string to_string() const { - if ((value_ == Value::HOUR) && hide_hour_unit_) { - return ""; - } - else { - return map_.unit_to_name(value_); - } - } - long to_long() const {return map_.unit_to_long(value_);} - Value to_value() const {return value_;} - void hide_hour_unit() { - hide_hour_unit_ = true; - } - - static std::vector unitOrder; - - private: - bool hide_hour_unit_ = false; - class Map { - public: - Map() { - for (const auto& entry : tab_) { - // unit_value <-> unit_name - name_to_value_[entry.unit_name] = entry.unit_value; - value_to_name_[entry.unit_value] = entry.unit_name; - - // unit_value <-> duration in seconds - value_to_duration_[entry.unit_value] = entry.duration; - duration_to_value_[entry.duration] = entry.unit_value; - - // unit_value <-> wmo_code - value_to_long_[entry.unit_value] = static_cast(entry.unit_value); - long_to_value_[static_cast(entry.unit_value)] = entry.unit_value; - } - } - - // wmo_code <-> unit_name - std::string unit_to_name(const Value& unit_value) const {return value_to_name_.at(unit_value);} - Value name_to_unit(const std::string& name) const {return name_to_value_.at(name);} - - // unit_value <-> duration - long unit_to_duration(const Value& unit_value) const {return value_to_duration_.at(unit_value);} - Value duration_to_unit(long duration) const {return duration_to_value_.at(duration);} - - // wmo_code <-> unit_name - long unit_to_long(const Value& unit_value) const {return value_to_long_.at(unit_value);} - Value long_to_unit(long wmo_code) const {return long_to_value_.at(wmo_code);} - - private: - struct Entry { - Unit::Value unit_value; - std::string unit_name; - long duration; - }; - - const std::array tab_ = { - Entry{Value::MISSING , "MISSING" , 0}, - Entry{Value::SECOND , "s" , 1}, - Entry{Value::MINUTE , "m" , 60}, - Entry{Value::MINUTES15 , "15m" , 900}, - Entry{Value::MINUTES30 , "30m" , 1800}, - Entry{Value::HOUR , "h" , 3600}, - Entry{Value::HOURS3 , "3h" , 10800}, - Entry{Value::HOURS6 , "6h" , 21600}, - Entry{Value::HOURS12 , "12h" , 43200}, - Entry{Value::DAY , "D" , 86400}, - Entry{Value::MONTH , "M" , 2592000}, - Entry{Value::YEAR , "Y" , 31536000}, - Entry{Value::YEARS10 , "10Y" , 315360000}, - Entry{Value::YEARS30 , "30Y" , 946080000}, - Entry{Value::CENTURY , "C" , 3153600000}, - }; - - std::unordered_map name_to_value_; - std::unordered_map value_to_name_; - - std::unordered_map value_to_long_; - std::unordered_map long_to_value_; - - std::unordered_map value_to_duration_; - std::unordered_map duration_to_value_; - }; - - - Value value_; - static Map map_; - public: - static Map& get_converter() {return map_;} - }; // Constructors - Step() : value_(0), unit_(Unit::Value::SECOND) {} - Step(T value, const Unit& unit); + 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); explicit Step(const std::string& str); // Getters T value() const { return value_; } - Unit unit() const { return unit_; } + UnitType unit() const { return unit_; } // Setters Step& setUnit(long new_unit); Step& setUnit(const std::string& new_unit); - Step& setUnit(const Step::Unit& new_unit); - Step& setUnit(const typename Step::Unit::Value 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_};} // 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();} private: T value_; - Unit unit_; + UnitType unit_; }; -template -//typename Step::Unit::Map Step::Unit::map_ = Step::Unit::Map(); -typename Step::Unit::Map Step::Unit::map_{}; - - -template -std::vector::Unit::Value> Step::Unit::unitOrder = { - Value::SECOND, - Value::MINUTE, - //{StepValue::MINUTES15, 900}, - //{StepValue::MINUTES30, 1800}, - Value::HOUR, - //{StepValue::HOURS3, 10800}, - //{StepValue::HOURS6, 21600}, - //{StepValue::HOURS12, 43200}, - //Value::DAY, - //Value::MONTH, - //{StepValue::YEAR, 31536000}, - //{StepValue::YEARS10, 315360000}, - //{StepValue::YEARS30, 946080000}, - //{StepValue::CENTURY, 3153600000}, - }; std::string parse_step(std::string step); @@ -259,7 +237,16 @@ template std::vector> parse_range(const std::string& range_ template -Step::Step(T value, long unit) : value_{value}, unit_{Unit{unit}} { +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."); @@ -267,7 +254,7 @@ Step::Step(T value, long unit) : value_{value}, unit_{Unit{unit}} { } template -Step::Step(T value, const std::string& unit) : value_{value}, unit_{Unit{unit}} { +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."); @@ -284,11 +271,11 @@ Step::Step(const std::string& str) { std::string u_str = str.substr(pos); int v = std::stoi(v_str); value_ = v; - unit_ = Unit{u_str}; + unit_ = UnitType{u_str}; } template -Step::Step(T value, const Unit& u) { +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."); @@ -305,19 +292,19 @@ Step& Step::optimizeUnit() { Seconds duration(0); switch (unit_.to_value()) { - case Unit::Value::SECOND: + case Unit::SECOND: duration = Seconds(value_); break; - case Unit::Value::MINUTE: + case Unit::MINUTE: duration = Minutes(value_); break; - case Unit::Value::HOUR: + case Unit::HOUR: duration = Hours(value_); break; - case Unit::Value::DAY: + case Unit::DAY: duration = Days(value_); break; - case Unit::Value::MONTH: + case Unit::MONTH: duration = Months(value_); break; default: @@ -327,8 +314,8 @@ Step& Step::optimizeUnit() { Seconds d = std::chrono::duration_cast>(duration); - for (auto it = Unit::unitOrder.rbegin(); it != Unit::unitOrder.rend(); ++it) { - long multiplier = Unit::get_converter().unit_to_duration(*it); + 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; @@ -341,25 +328,25 @@ Step& Step::optimizeUnit() { template Step& Step::setUnit(const std::string& unit_name) { - setUnit(Unit{unit_name}); + setUnit(UnitType{unit_name}); return *this; } template Step& Step::setUnit(long unit_code) { - setUnit(Unit{unit_code}); + setUnit(UnitType{unit_code}); return *this; } template -Step& Step::setUnit(const Step::Unit& new_unit) { +Step& Step::setUnit(const UnitType& new_unit) { setUnit(new_unit.to_value()); return *this; } template -Step& Step::setUnit(const typename Step::Unit::Value new_unit) { +Step& Step::setUnit(const Unit new_unit) { if (value_ == 0) { unit_ = new_unit; return *this; @@ -369,19 +356,19 @@ Step& Step::setUnit(const typename Step::Unit::Value new_unit) { } Seconds duration(0); switch (unit_.to_value()) { - case Unit::Value::SECOND: + case Unit::SECOND: duration = Seconds(value_); break; - case Unit::Value::MINUTE: + case Unit::MINUTE: duration = Minutes(value_); break; - case Unit::Value::HOUR: + case Unit::HOUR: duration = Hours(value_); break; - case Unit::Value::DAY: + case Unit::DAY: duration = Days(value_); break; - case Unit::Value::MONTH: + case Unit::MONTH: duration = Months(value_); break; default: @@ -390,23 +377,23 @@ Step& Step::setUnit(const typename Step::Unit::Value new_unit) { } switch (new_unit) { - case Unit::Value::SECOND: + case Unit::SECOND: value_ = duration.count(); break; - case Unit::Value::MINUTE: + case Unit::MINUTE: value_ = std::chrono::duration_cast>(duration).count(); break; - case Unit::Value::HOUR: + case Unit::HOUR: value_ = std::chrono::duration_cast>(duration).count(); break; - case Unit::Value::DAY: + case Unit::DAY: value_ = std::chrono::duration_cast>(duration).count(); break; - case Unit::Value::MONTH: + case Unit::MONTH: value_ = std::chrono::duration_cast>(duration).count(); break; default: - std::string msg = "Unknown unit: " + Step::Unit{new_unit}.to_string(); + std::string msg = "Unknown unit: " + UnitType{new_unit}.to_string(); throw std::runtime_error(msg); } unit_ = new_unit; diff --git a/src/step_utilities.cc b/src/step_utilities.cc index 19c5cacbd..b216d9d57 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -18,20 +18,25 @@ std::optional> getStep(grib_handle* h, const std::string& value_key, } } + std::optional> getForecastTime(grib_handle* h) { return getStep(h, "forecastTime", "indicatorOfUnitOfTimeRange"); } + 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())}; } + + bool futureOutputEnabled(grib_handle* h) { int ret = 0; size_t stepOutputFormatSize = 128; diff --git a/src/step_utilities.h b/src/step_utilities.h index 2ac9e3e49..21ec426db 100644 --- a/src/step_utilities.h +++ b/src/step_utilities.h @@ -9,4 +9,36 @@ std::optional> getStep(grib_handle* h, const std::string& value_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); 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 90a3f59f0..a46f111a1 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -10,6 +10,20 @@ . ./include.ctest.sh +grib_expect_failure() +{ + a_file=$1 + a_params=$2 + ${tools_dir}/grib_get $a_params $a_file > /dev/null 2>&1 + if [ $? -eq 0 ]; then + echo "File: '$a_file'" + echo "Key(s): '$a_params'" + echo "Expected: 'failure'" + echo "Result: 'success'" + exit 1 + fi +} + grib_check_key_equals() { a_file=$1 @@ -37,16 +51,59 @@ 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=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_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" + +exit + + + +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=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" + ${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "59 m" @@ -117,7 +174,7 @@ grib_check_key_equals $temp "-p $low_level_keys" "0 m 2 h" grib_check_key_equals $temp "-p $keys__" "0-2 0 2" grib_check_key_equals $temp "-y -p $keys__" "0-2 0 2" grib_check_key_equals $temp "-p $keys_s" "0-2 0 2" -grib_check_key_equals $temp "-y -p $keys_s" "0-2 0m 2" +grib_check_key_equals $temp "-y -p $keys_s" "0-2 0 2" grib_check_key_equals $temp "-p $keys_i" "2 0 2" grib_check_key_equals $temp "-y -p $keys_i" "2 0 2" grib_check_key_equals $temp "-p $keys_d" "2 0 2" @@ -157,12 +214,12 @@ ${tools_dir}/grib_set -s forecastTime=45,indicatorOfUnitOfTimeRange=m,lengthOfTi grib_check_key_equals $temp "-p $low_level_keys" "45 m 15 m" grib_check_key_equals $temp "-p $keys__" "45-60 45 60" grib_check_key_equals $temp "-y -p $keys__" "45m-60m 45 60" -grib_check_key_equals $temp "-p $keys_s" "45-60 45 1" -grib_check_key_equals $temp "-y -p $keys_s" "45m-60m 45m 1" +grib_check_key_equals $temp "-p $keys_s" "45-60 45 60" +grib_check_key_equals $temp "-y -p $keys_s" "45m-60m 45m 60m" grib_check_key_equals $temp "-p $keys_i" "60 45 60" -grib_check_key_equals $temp "-y -p $keys_i" "1 45 60" +grib_check_key_equals $temp "-y -p $keys_i" "60 45 60" grib_check_key_equals $temp "-p $keys_d" "60 45 60" -grib_check_key_equals $temp "-y -p $keys_d" "1 45 60" +grib_check_key_equals $temp "-y -p $keys_d" "60 45 60" ${tools_dir}/grib_set -s forecastTime=60,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=2,indicatorOfUnitForTimeRange=h $fn $temp @@ -193,9 +250,9 @@ 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" +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" +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" ${tools_dir}/grib_set -s forecastTime=1080,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=6,indicatorOfUnitForTimeRange=h $fn $temp From 9cd5041d537f2190278af887eba53287e31e44fb Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 25 Aug 2023 06:10:07 +0000 Subject: [PATCH 016/125] 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 From 14b44d3e0fc0b40e49aec0b88d7468383ecebc1b Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 25 Aug 2023 06:21:14 +0000 Subject: [PATCH 017/125] ECC-1620: Add missing file --- src/grib_accessor_class_optimal_step_units.cc | 252 ++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 src/grib_accessor_class_optimal_step_units.cc diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc new file mode 100644 index 000000000..4db104569 --- /dev/null +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -0,0 +1,252 @@ +/* + * (C) Copyright 2005- ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * + * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by + * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. + */ + +/********************************************* + * Enrico Fucile + *******************************************/ + +#include "grib_api_internal.h" +#include "step.h" +#include "step_utilities.h" +/* + This is used by make_class.pl + + START_CLASS_DEF + CLASS = accessor + SUPER = grib_accessor_class_gen + IMPLEMENTS = pack_long;unpack_long;dump + IMPLEMENTS = pack_string;unpack_string;dump + IMPLEMENTS = get_native_type;string_length + IMPLEMENTS = init + MEMBERS = const char* forecastTime + MEMBERS = const char* indicatorOfUnitOfTimeRange + MEMBERS = const char* lengthOfTimeRange + MEMBERS = const char* indicatorOfUnitForTimeRange + END_CLASS_DEF + + */ + +/* START_CLASS_IMP */ + +/* + +Don't edit anything between START_CLASS_IMP and END_CLASS_IMP +Instead edit values between START_CLASS_DEF and END_CLASS_DEF +or edit "accessor.class" and rerun ./make_class.pl + +*/ + +static int get_native_type(grib_accessor*); +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_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 void dump(grib_accessor*, grib_dumper*); +static void init(grib_accessor*, const long, grib_arguments*); + +typedef struct grib_accessor_optimal_step_units +{ + grib_accessor att; + /* Members defined in gen */ + /* Members defined in optimal_step_units */ + const char* forecastTime; + const char* indicatorOfUnitOfTimeRange; + const char* lengthOfTimeRange; + const char* indicatorOfUnitForTimeRange; +} grib_accessor_optimal_step_units; + +extern grib_accessor_class* grib_accessor_class_gen; + +static grib_accessor_class _grib_accessor_class_optimal_step_units = { + &grib_accessor_class_gen, /* super */ + "optimal_step_units", /* name */ + sizeof(grib_accessor_optimal_step_units), /* size */ + 0, /* inited */ + 0, /* init_class */ + &init, /* init */ + 0, /* post_init */ + 0, /* destroy */ + &dump, /* dump */ + 0, /* next_offset */ + &string_length, /* get length of string */ + 0, /* get number of values */ + 0, /* get number of bytes */ + 0, /* get offset to bytes */ + &get_native_type, /* get native type */ + 0, /* get sub_section */ + 0, /* pack_missing */ + 0, /* is_missing */ + &pack_long, /* pack_long */ + &unpack_long, /* unpack_long */ + 0, /* pack_double */ + 0, /* pack_float */ + 0, /* unpack_double */ + 0, /* unpack_float */ + &pack_string, /* pack_string */ + &unpack_string, /* unpack_string */ + 0, /* pack_string_array */ + 0, /* unpack_string_array */ + 0, /* pack_bytes */ + 0, /* unpack_bytes */ + 0, /* pack_expression */ + 0, /* notify_change */ + 0, /* update_size */ + 0, /* preferred_size */ + 0, /* resize */ + 0, /* nearest_smaller_value */ + 0, /* next accessor */ + 0, /* compare vs. another accessor */ + 0, /* unpack only ith value (double) */ + 0, /* unpack only ith value (float) */ + 0, /* unpack a given set of elements (double) */ + 0, /* unpack a given set of elements (float) */ + 0, /* unpack a subarray */ + 0, /* clear */ + 0, /* clone accessor */ +}; + + +grib_accessor_class* grib_accessor_class_optimal_step_units = &_grib_accessor_class_optimal_step_units; + +/* END_CLASS_IMP */ + +static void init(grib_accessor* a, const long l, grib_arguments* c) +{ + grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; + + int n = 0; + + self->forecastTime = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->indicatorOfUnitOfTimeRange = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->lengthOfTimeRange = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->indicatorOfUnitForTimeRange= grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + a->length = 0; +} + +static void dump(grib_accessor* a, grib_dumper* dumper) +{ + grib_dump_string(dumper, a, NULL); +} + + +static int value_count(grib_accessor* a, long* count) +{ + *count = 1; + return 0; +} + +static size_t string_length(grib_accessor* a) +{ + return 255; +} + +static long staticStepUnits = UnitType{Unit::MISSING}.toLong(); + +static int pack_long(grib_accessor* a, const long* val, size_t* len) +{ + //grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; + //grib_handle* h = grib_handle_of_accessor(a); + //int ret = 0; + + //auto range = getTimeRange(h); + //Step startStep = range.startStep(); + //Step endStep = range.endStep(); + //startStep.setUnit(UnitType{*val}); + //endStep.setUnit(UnitType{*val}); + + //if ((ret = grib_set_long_internal(h, "forecastTime", startStep.value())) != GRIB_SUCCESS) + // return ret; + //if ((ret = grib_set_long_internal(h, self->indicatorOfUnitOfTimeRange, startStep.unit().toLong())) != GRIB_SUCCESS) + // return ret; + + //if (grib_is_defined(h, "lengthOfTimeRange")) { + // if ((ret = grib_set_long_internal(h, "lengthOfTimeRange", (endStep - startStep).value())) != GRIB_SUCCESS) + // return ret; + // if ((ret = grib_set_long_internal(h, self->indicatorOfUnitForTimeRange, (endStep - startStep).unit().toLong())) != GRIB_SUCCESS) + // return ret; + //} + staticStepUnits = *val; + + return GRIB_SUCCESS; +} + +static int unpack_long(grib_accessor* a, long* val, size_t* len) +{ + if (staticStepUnits != 255) { + *val = staticStepUnits; + return GRIB_SUCCESS; + } + grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; + grib_handle* h = grib_handle_of_accessor(a); + int ret = 0; + + auto start_step_opt = getStep(h, self->forecastTime, self->indicatorOfUnitOfTimeRange); + auto end_step_opt = getStep(h, self->lengthOfTimeRange, self->indicatorOfUnitForTimeRange); + + if (!(start_step_opt && end_step_opt)) { + *val = UnitType{Unit::HOUR}.toLong(); + } + + Step start_step = start_step_opt.value_or(Step{}); + Step end_step = end_step_opt.value_or(Step{}); + + auto [step_a, step_b] = findCommonUnits(start_step.optimizeUnit(), end_step.optimizeUnit()); + *val = step_a.unit().toLong(); + return GRIB_SUCCESS; +} + + +static int pack_string(grib_accessor* a, const char* val, size_t* len) +{ + //grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; + //grib_handle* h = grib_handle_of_accessor(a); + //int ret = 0; + + //auto range = getTimeRange(h); + //Step startStep = range.startStep(); + //Step endStep = range.endStep(); + //UnitType unit{val}; + //startStep.setUnit(unit); + //endStep.setUnit(unit); + + + //if ((ret = grib_set_long_internal(h, "forecastTime", startStep.value())) != GRIB_SUCCESS) + // return ret; + //if ((ret = grib_set_long_internal(h, self->indicatorOfUnitOfTimeRange, startStep.unit().toLong())) != GRIB_SUCCESS) + // return ret; + + //if (grib_is_defined(h, "lengthOfTimeRange")) { + // if ((ret = grib_set_long_internal(h, "lengthOfTimeRange", (endStep - startStep).value())) != GRIB_SUCCESS) + // return ret; + // if ((ret = grib_set_long_internal(h, self->indicatorOfUnitForTimeRange, (endStep - startStep).unit().toLong())) != GRIB_SUCCESS) + // return ret; + //} + staticStepUnits = UnitType{val}.toLong(); + + return GRIB_SUCCESS; +} + +static int unpack_string(grib_accessor* a, char* val, size_t* len) +{ + int ret = 0; + long unit = 0; + size_t unit_len = 0; + if ((ret = unpack_long(a, &unit, &unit_len)) != GRIB_SUCCESS) + return ret; + *len = snprintf(val, *len, "%s", UnitType{unit}.toString().c_str()); + return GRIB_SUCCESS; +} + + +static int get_native_type(grib_accessor* a) +{ + return GRIB_TYPE_LONG; +} From ac854208bdd005d8c3eafe18d4f858a173564ebf Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 25 Aug 2023 06:35:19 +0000 Subject: [PATCH 018/125] ECC-1620: Refactoring and clean-up --- src/grib_accessor_class_g2end_step.cc | 93 +++---------------- src/grib_accessor_class_g2step_range.cc | 49 +++------- src/grib_accessor_class_optimal_step_units.cc | 61 ++---------- ...grib_accessor_class_step_human_readable.cc | 12 +-- src/grib_accessor_class_step_in_units.cc | 57 +++--------- src/step.cc | 62 ++++++------- src/step.h | 66 ++++++------- src/step_utilities.cc | 30 ++---- src/step_utilities.h | 9 +- 9 files changed, 123 insertions(+), 316 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 304cc772f..b8ab3b411 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -376,21 +376,11 @@ 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; - if ((err = grib_get_long_internal(h, self->start_step, &start_step))) - return err; + if ((ret = grib_get_long_internal(h, self->start_step, &start_step))) + return ret; /* point in time */ if (self->year == NULL) { @@ -399,8 +389,8 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) } Assert(self->numberOfTimeRange); - if ((err = grib_get_long_internal(h, self->numberOfTimeRange, &numberOfTimeRange))) - return err; + if ((ret = grib_get_long_internal(h, self->numberOfTimeRange, &numberOfTimeRange))) + return ret; Assert(numberOfTimeRange == 1 || numberOfTimeRange == 2); if (numberOfTimeRange == 1) { @@ -411,7 +401,6 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) ret = unpack_multiple_time_ranges(a, val, len); return ret; } - //} return GRIB_SUCCESS; } @@ -534,7 +523,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) 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) + if ((ret = grib_set_long_internal(h, "stepUnits", UnitType{Unit::SECOND}.to_long())) != GRIB_SUCCESS) return ret; long step_value; @@ -544,45 +533,20 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) Step step(step_value, Unit::SECOND); - step.setUnit(step_units_old); + step.set_unit(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, "%s", step.toString().c_str()); + step.hide_hour_unit(); + if (is_future_output_enabled(h)) { + snprintf(val, *len, "%s", step.to_string().c_str()); } else { 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; } @@ -597,8 +561,8 @@ static int pack_double(grib_accessor* a, const double* val, size_t* len) 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) + end_step.optimize_unit(); + if ((ret = grib_set_long_internal(h, "stepUnits", end_step.unit().to_long())) != GRIB_SUCCESS) return ret; long end_step_value = end_step.value(); @@ -615,8 +579,8 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) 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) + end_step.optimize_unit(); + if ((ret = grib_set_long_internal(h, "stepUnits", end_step.unit().to_long())) != GRIB_SUCCESS) return ret; double end_step_value = end_step.value(); @@ -625,37 +589,6 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) 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; - //} } diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index b103f02f6..05bf65be7 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -14,7 +14,6 @@ #include "grib_api_internal.h" #include "step.h" -#include "step_range.h" #include "step_utilities.h" #include /* @@ -155,10 +154,10 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) Step start_step = Step(start_value, step_units_value); - start_step.hideHourUnit(); + start_step.hide_hour_unit(); if (self->endStep == NULL) { - if (futureOutputEnabled(h)) { - snprintf(buf, sizeof(buf), "%s", start_step.toString().c_str()); + if (is_future_output_enabled(h)) { + snprintf(buf, sizeof(buf), "%s", start_step.to_string().c_str()); } else { snprintf(buf, sizeof(buf), "%ld", start_value); @@ -168,14 +167,14 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) if ((ret = grib_get_long_internal(h, self->endStep, &end_value)) != GRIB_SUCCESS) return ret; - if (futureOutputEnabled(h)) { + if (is_future_output_enabled(h)) { Step end_step = Step(end_value, step_units_value); - end_step.hideHourUnit(); + end_step.hide_hour_unit(); if (start_value == end_value) { - snprintf(buf, sizeof(buf), "%s", end_step.toString().c_str()); + snprintf(buf, sizeof(buf), "%s", end_step.to_string().c_str()); } else { - snprintf(buf, sizeof(buf), "%s-%s", start_step.toString().c_str(), end_step.toString().c_str()); + snprintf(buf, sizeof(buf), "%s-%s", start_step.to_string().c_str(), end_step.to_string().c_str()); } } else { @@ -208,15 +207,15 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - std::vector steps = parseRange(val); + std::vector steps = parse_range(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()))) + std::tie(step_0, step_1) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); + if ((ret = grib_set_long_internal(h, "stepUnits", step_0.unit().to_long()))) return ret; } @@ -273,7 +272,7 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) return ret; Step start_step = Step(start_value, step_units_value); - start_step.hideHourUnit(); + start_step.hide_hour_unit(); if (self->endStep == NULL) { *val = start_step.value(); } @@ -285,18 +284,6 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) } 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) @@ -316,7 +303,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) return ret; Step start_step = Step(start_value, step_units_value); - start_step.hideHourUnit(); + start_step.hide_hour_unit(); if (self->endStep == NULL) { *val = start_step.value(); } @@ -328,18 +315,6 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) } 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 get_native_type(grib_accessor* a) diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 4db104569..e670034c6 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -148,31 +148,10 @@ static size_t string_length(grib_accessor* a) return 255; } -static long staticStepUnits = UnitType{Unit::MISSING}.toLong(); +static long staticStepUnits = UnitType{Unit::MISSING}.to_long(); static int pack_long(grib_accessor* a, const long* val, size_t* len) { - //grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; - //grib_handle* h = grib_handle_of_accessor(a); - //int ret = 0; - - //auto range = getTimeRange(h); - //Step startStep = range.startStep(); - //Step endStep = range.endStep(); - //startStep.setUnit(UnitType{*val}); - //endStep.setUnit(UnitType{*val}); - - //if ((ret = grib_set_long_internal(h, "forecastTime", startStep.value())) != GRIB_SUCCESS) - // return ret; - //if ((ret = grib_set_long_internal(h, self->indicatorOfUnitOfTimeRange, startStep.unit().toLong())) != GRIB_SUCCESS) - // return ret; - - //if (grib_is_defined(h, "lengthOfTimeRange")) { - // if ((ret = grib_set_long_internal(h, "lengthOfTimeRange", (endStep - startStep).value())) != GRIB_SUCCESS) - // return ret; - // if ((ret = grib_set_long_internal(h, self->indicatorOfUnitForTimeRange, (endStep - startStep).unit().toLong())) != GRIB_SUCCESS) - // return ret; - //} staticStepUnits = *val; return GRIB_SUCCESS; @@ -188,49 +167,25 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - auto start_step_opt = getStep(h, self->forecastTime, self->indicatorOfUnitOfTimeRange); - auto end_step_opt = getStep(h, self->lengthOfTimeRange, self->indicatorOfUnitForTimeRange); + auto start_step_opt = get_step(h, self->forecastTime, self->indicatorOfUnitOfTimeRange); + auto end_step_opt = get_step(h, self->lengthOfTimeRange, self->indicatorOfUnitForTimeRange); if (!(start_step_opt && end_step_opt)) { - *val = UnitType{Unit::HOUR}.toLong(); + *val = UnitType{Unit::HOUR}.to_long(); } Step start_step = start_step_opt.value_or(Step{}); Step end_step = end_step_opt.value_or(Step{}); - auto [step_a, step_b] = findCommonUnits(start_step.optimizeUnit(), end_step.optimizeUnit()); - *val = step_a.unit().toLong(); + auto [step_a, step_b] = find_common_units(start_step.optimize_unit(), end_step.optimize_unit()); + *val = step_a.unit().to_long(); return GRIB_SUCCESS; } static int pack_string(grib_accessor* a, const char* val, size_t* len) { - //grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; - //grib_handle* h = grib_handle_of_accessor(a); - //int ret = 0; - - //auto range = getTimeRange(h); - //Step startStep = range.startStep(); - //Step endStep = range.endStep(); - //UnitType unit{val}; - //startStep.setUnit(unit); - //endStep.setUnit(unit); - - - //if ((ret = grib_set_long_internal(h, "forecastTime", startStep.value())) != GRIB_SUCCESS) - // return ret; - //if ((ret = grib_set_long_internal(h, self->indicatorOfUnitOfTimeRange, startStep.unit().toLong())) != GRIB_SUCCESS) - // return ret; - - //if (grib_is_defined(h, "lengthOfTimeRange")) { - // if ((ret = grib_set_long_internal(h, "lengthOfTimeRange", (endStep - startStep).value())) != GRIB_SUCCESS) - // return ret; - // if ((ret = grib_set_long_internal(h, self->indicatorOfUnitForTimeRange, (endStep - startStep).unit().toLong())) != GRIB_SUCCESS) - // return ret; - //} - staticStepUnits = UnitType{val}.toLong(); - + staticStepUnits = UnitType{val}.to_long(); return GRIB_SUCCESS; } @@ -241,7 +196,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) size_t unit_len = 0; if ((ret = unpack_long(a, &unit, &unit_len)) != GRIB_SUCCESS) return ret; - *len = snprintf(val, *len, "%s", UnitType{unit}.toString().c_str()); + *len = snprintf(val, *len, "%s", UnitType{unit}.to_string().c_str()); return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_step_human_readable.cc b/src/grib_accessor_class_step_human_readable.cc index ebd2c4a7b..b275c444a 100644 --- a/src/grib_accessor_class_step_human_readable.cc +++ b/src/grib_accessor_class_step_human_readable.cc @@ -125,14 +125,14 @@ static int get_step_human_readable(grib_handle* h, char* result, size_t* length) size_t slen = 2; long step; - //size_t stepOutputFormatSize = 128; - //char stepOutputFormat[stepOutputFormatSize]; - //if ((err = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) { - // printf("ERROR: unable to get stepOutputFormat stepOutputFormat=%s\n", stepOutputFormat); + //size_t step_output_format_size = 128; + //char step_output_format[step_output_format_size]; + //if ((err = grib_get_string_internal(h, "step_output_format", step_output_format, &step_output_format_size)) != GRIB_SUCCESS) { + // printf("ERROR: unable to get step_output_format step_output_format=%s\n", step_output_format); // return err; //} - //if (strcmp(stepOutputFormat, "future") == 0) { + //if (strcmp(step_output_format, "future") == 0) { /* Change units to seconds (highest resolution) * before computing the step value */ @@ -143,7 +143,7 @@ static int get_step_human_readable(grib_handle* h, char* result, size_t* length) // long indicator = grib_get_long(h, "indicatorOfUnitOfTimeRange", &indicator); // auto stepOptimizer = Step(step, indicator); - // stepOptimizer.optimizeUnit(); + // stepOptimizer.optimize_unit(); // snprintf(result, 1024, "%d%s", stepOptimizer.value(), stepOptimizer.unit_as_str().c_str()); //} diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index e26e5a3ed..27d33e627 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -282,22 +282,14 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) int ret = 0; Step step = step_from_string(val); - step.optimizeUnit(); + step.optimize_unit(); - if ((ret = grib_set_long_internal(h, self->stepUnits, step.unit().toLong()))) + if ((ret = grib_set_long_internal(h, self->stepUnits, step.unit().to_long()))) return ret; long step_value = step.value(); if ((ret = pack_long(a, &step_value, len)) != GRIB_SUCCESS) 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; } @@ -311,7 +303,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) 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) + if ((ret = grib_set_long_internal(h, "stepUnits", UnitType{Unit::SECOND}.to_long())) != GRIB_SUCCESS) return ret; long step_value; @@ -321,35 +313,20 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) Step step(step_value, Unit::SECOND); - step.setUnit(step_units_old); + step.set_unit(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, "%s", step.toString().c_str()); + step.hide_hour_unit(); + if (is_future_output_enabled(h)) { + snprintf(val, *len, "%s", step.to_string().c_str()); } else { 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; } @@ -364,8 +341,8 @@ static int pack_double(grib_accessor* a, const double* val, size_t* len) return ret; Step start_step{*val, step_units}; - start_step.optimizeUnit(); - if ((ret = grib_set_long_internal(h, "stepUnits", start_step.unit().toLong())) != GRIB_SUCCESS) + start_step.optimize_unit(); + if ((ret = grib_set_long_internal(h, "stepUnits", start_step.unit().to_long())) != GRIB_SUCCESS) return ret; long start_step_value = start_step.value(); @@ -387,7 +364,7 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) return ret; UnitType step_units{step_units_old}; - if ((ret = grib_set_long_internal(h, "stepUnits", UnitType{Unit::SECOND}.toLong())) != GRIB_SUCCESS) + if ((ret = grib_set_long_internal(h, "stepUnits", UnitType{Unit::SECOND}.to_long())) != GRIB_SUCCESS) return ret; long value_secs; @@ -396,19 +373,7 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) return ret; Step step(value_secs, Unit::SECOND); - step.setUnit(step_units_old); + step.set_unit(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/step.cc b/src/step.cc index d1f1faa5e..21b5929ee 100644 --- a/src/step.cc +++ b/src/step.cc @@ -35,7 +35,7 @@ Step step_from_string(std::string step) { throw std::runtime_error("Could not parse step: " + step); } -std::vector parseRange(const std::string& range_str) { +std::vector parse_range(const std::string& range_str) { std::vector steps; std::string::size_type pos = 0; std::string::size_type prev = 0; @@ -57,14 +57,14 @@ bool Step::operator==(const Step& other) const { Step Step::operator+(const Step& step) { Step tmp = step; - auto [a, b] = findCommonUnits(this->optimizeUnit(), tmp.optimizeUnit()); + auto [a, b] = find_common_units(this->optimize_unit(), tmp.optimize_unit()); assert(a.internal_unit_ == b.internal_unit_); return Step(a.internal_value_ + b.internal_value_, a.internal_unit_); } Step Step::operator-(const Step& step) { Step tmp = step; - auto [a, b] = findCommonUnits(this->optimizeUnit(), tmp.optimizeUnit()); + auto [a, b] = find_common_units(this->optimize_unit(), tmp.optimize_unit()); assert(a.internal_unit_ == b.internal_unit_); if (a.internal_value_ < b.internal_value_) { throw std::runtime_error("Negative step not supported"); @@ -72,7 +72,7 @@ Step Step::operator-(const Step& step) { return Step(a.internal_value_ - b.internal_value_, a.internal_unit_); } -std::pair findCommonUnits(const Step& startStep, const Step& endStep) { +std::pair find_common_units(const Step& startStep, const Step& endStep) { Step a = startStep; Step b = endStep; @@ -98,13 +98,13 @@ std::pair findCommonUnits(const Step& startStep, const Step& endStep 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(); + return e == a.unit().to_value() || e == b.unit().to_value(); }); assert(it != UnitType::unitOrder.end()); - a.setUnit(*it); - b.setUnit(*it); + a.set_unit(*it); + b.set_unit(*it); a.recalculateValue(); b.recalculateValue(); assert(a.internal_unit_ == b.internal_unit_); @@ -113,7 +113,7 @@ std::pair findCommonUnits(const Step& startStep, const Step& endStep return {a, b}; } -void Step::sanityCheck() const { +void Step::sanity_check() 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."); @@ -121,28 +121,28 @@ void Step::sanityCheck() const { } -void Step::initLong(long value, const UnitType& unit) { +void Step::init_long(long value, const UnitType& unit) { internal_value_ = value; internal_unit_ = unit; unit_ = internal_unit_; - sanityCheck(); + sanity_check(); } -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(); +void Step::init_double(double value, const UnitType& unit) { + long seconds = UnitType::get_converter().unit_to_duration(unit.to_value()); + init_long(static_cast(value * seconds), UnitType{Unit::SECOND}); + optimize_unit(); } -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(double value, const UnitType& unit) : internal_unit_{unit}, unit_{internal_unit_} {init_double(value, unit);} +Step::Step(double value, Unit unit) {init_double(value, UnitType{unit});} +Step::Step(double value, long unit) {init_double(value, UnitType{unit});} +Step::Step(double value, const std::string& unit) {init_double(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(long value, const UnitType& unit) { init_long(value, unit);} +Step::Step(long value, Unit unit) {init_long(value, UnitType{unit});} +Step::Step(long value, long unit) {init_long(value, UnitType{unit});} +Step::Step(long value, const std::string& unit) {init_long(value, UnitType{unit});} Step::Step(const std::string& str) { //size_t pos = str.find_first_of("smhDMYC"); @@ -154,18 +154,18 @@ Step::Step(const std::string& str) { std::string u_str = str.substr(pos); double v = std::stod(v_str); - initDouble(v, UnitType{u_str}); + init_double(v, UnitType{u_str}); } -Step& Step::optimizeUnit() { +Step& Step::optimize_unit() { if (internal_value_ == 0) { return *this; } unit_ = internal_unit_; Seconds duration(0); - switch (internal_unit_.toValue()) { + switch (internal_unit_.to_value()) { case Unit::SECOND: duration = Seconds(internal_value_); break; @@ -182,14 +182,14 @@ Step& Step::optimizeUnit() { duration = Months(internal_value_); break; default: - std::string msg = "Unknown unit: " + internal_unit_.toString(); + std::string msg = "Unknown unit: " + internal_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::getConverter().unit_to_duration(*it); + long multiplier = UnitType::get_converter().unit_to_duration(*it); if (d.count() % multiplier == 0) { internal_value_ = duration.count() / multiplier; internal_unit_ = *it; @@ -201,22 +201,22 @@ Step& Step::optimizeUnit() { return *this; } -Step& Step::setUnit(const std::string& unit_name) { +Step& Step::set_unit(const std::string& unit_name) { unit_ = UnitType{unit_name}; return *this; } -Step& Step::setUnit(long unit_code) { +Step& Step::set_unit(long unit_code) { unit_ = UnitType{unit_code}; return *this; } -Step& Step::setUnit(const UnitType& new_unit) { +Step& Step::set_unit(const UnitType& new_unit) { unit_ = new_unit; return *this; } -Step& Step::setUnit(const Unit new_unit) { +Step& Step::set_unit(const Unit new_unit) { unit_ = new_unit; return *this; } diff --git a/src/step.h b/src/step.h index 52c8b9f17..a39daf989 100644 --- a/src/step.h +++ b/src/step.h @@ -70,7 +70,7 @@ public: return *this; } - std::string toString() const { + std::string to_string() const { if ((internal_value_ == Unit::HOUR) && hide_hour_unit_) { return ""; } @@ -78,10 +78,10 @@ public: return map_.unit_to_name(internal_value_); } } - 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;} + long to_long() const {return map_.unit_to_long(internal_value_);} + Unit to_value() const {return internal_value_;} + void hide_hour_unit() {hide_hour_unit_ = true;} + void show_hour_unit() {hide_hour_unit_ = false;} static std::vector unitOrder; private: @@ -155,7 +155,7 @@ private: Unit internal_value_; static Map map_; public: - static Map& getConverter() {return map_;} + static Map& get_converter() {return map_;} }; @@ -179,10 +179,10 @@ public: 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& set_unit(long new_unit); + Step& set_unit(const std::string& new_unit); + Step& set_unit(const Unit new_unit); + Step& set_unit(const UnitType& new_unit); // Operators bool operator==(const Step& other) const; @@ -191,31 +191,31 @@ public: Step operator-(const Step& step); // Methods - Step& optimizeUnit(); - friend std::pair findCommonUnits(const Step& startStep, const Step& endStep); - void hideHourUnit() { - internal_unit_.hideHourUnit(); - unit_.hideHourUnit(); + Step& optimize_unit(); + friend std::pair find_common_units(const Step& startStep, const Step& endStep); + void hide_hour_unit() { + internal_unit_.hide_hour_unit(); + unit_.hide_hour_unit(); } - void showHourUnit() { - internal_unit_.showHourUnit(); - unit_.showHourUnit(); + void show_hour_unit() { + internal_unit_.show_hour_unit(); + unit_.show_hour_unit(); } - std::string toString() const { + std::string to_string() const { std::stringstream ss; if (value() == value()) { - ss << value() << unit_.toString(); + ss << value() << unit_.to_string(); } else { - ss << value() << unit_.toString(); + ss << value() << unit_.to_string(); } return ss.str(); } private: - void initLong(long value, const UnitType& unit); - void initDouble(double value, const UnitType& unit); - void sanityCheck() const; + void init_long(long value, const UnitType& unit); + void init_double(double value, const UnitType& unit); + void sanity_check() const; Step& recalculateValue() { if (internal_value_ == 0) { internal_unit_ = unit_; @@ -223,7 +223,7 @@ private: } Seconds secs(0); - switch (internal_unit_.toValue()) { + switch (internal_unit_.to_value()) { case Unit::SECOND: secs = Seconds(internal_value_); break; @@ -240,11 +240,11 @@ private: secs = Months(internal_value_); break; default: - std::string msg = "Unknown unit: " + internal_unit_.toString(); + std::string msg = "Unknown unit: " + internal_unit_.to_string(); throw std::runtime_error(msg); } - long multiplier = UnitType::getConverter().unit_to_duration(unit_.toValue()); + long multiplier = UnitType::get_converter().unit_to_duration(unit_.to_value()); internal_value_ = secs.count() / multiplier; internal_unit_ = unit_; @@ -258,8 +258,8 @@ private: 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::vector parse_range(const std::string& range_str); +std::pair find_common_units(const Step& startStep, const Step& endStep); template T Step::value() const { @@ -270,7 +270,7 @@ template T Step::value() const { return internal_value_; } Seconds duration(0); - switch (internal_unit_.toValue()) { + switch (internal_unit_.to_value()) { case Unit::SECOND: duration = Seconds(internal_value_); break; @@ -287,12 +287,12 @@ template T Step::value() const { duration = Months(internal_value_); break; default: - std::string msg = "Unknown unit: " + internal_unit_.toString(); + std::string msg = "Unknown unit: " + internal_unit_.to_string(); throw std::runtime_error(msg); } T value = 0; - switch (unit_.toValue()) { + switch (unit_.to_value()) { case Unit::SECOND: value = duration.count(); break; @@ -309,7 +309,7 @@ template T Step::value() const { value = std::chrono::duration_cast>(duration).count(); break; default: - std::string msg = "Unknown unit: " + UnitType{unit_}.toString(); + std::string msg = "Unknown unit: " + UnitType{unit_}.to_string(); throw std::runtime_error(msg); } return value; diff --git a/src/step_utilities.cc b/src/step_utilities.cc index 575ae8384..284c9ec08 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -1,7 +1,8 @@ //#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 get_step(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) @@ -19,28 +20,11 @@ std::optional getStep(grib_handle* h, const std::string& value_key, const } -//std::optional getForecastTime(grib_handle* h) { -// return getStep(h, "forecastTime", "indicatorOfUnitOfTimeRange"); -//} - - -//std::optional getLengthOfTimeRange(grib_handle* h) { -// return getStep(h, "lengthOfTimeRange", "indicatorOfUnitForTimeRange"); -//} - - -//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) { - size_t stepOutputFormatSize = 128; - char stepOutputFormat[stepOutputFormatSize]; +bool is_future_output_enabled(grib_handle* h) { + size_t step_output_format_size = 128; + char step_output_format[step_output_format_size]; int ret = 0; - if ((ret = grib_get_string_internal(h, "stepOutputFormat", stepOutputFormat, &stepOutputFormatSize)) != GRIB_SUCCESS) + if ((ret = grib_get_string_internal(h, "step_output_format", step_output_format, &step_output_format_size)) != GRIB_SUCCESS) return ret; - return strcmp(stepOutputFormat, "future") == 0; + return strcmp(step_output_format, "future") == 0; } diff --git a/src/step_utilities.h b/src/step_utilities.h index fddcd1f9c..d6733e0e4 100644 --- a/src/step_utilities.h +++ b/src/step_utilities.h @@ -3,12 +3,7 @@ #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); -//StepRange getTimeRange(grib_handle* h); -bool futureOutputEnabled(grib_handle* h); +std::optional get_step(grib_handle* h, const std::string& value_key, const std::string& unit_key); +bool is_future_output_enabled(grib_handle* h); From e243ccff4a80dd7da658de5722cc4e959154b393 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 25 Aug 2023 06:45:38 +0000 Subject: [PATCH 019/125] ECC-1620: Fix key name --- src/step_utilities.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/step_utilities.cc b/src/step_utilities.cc index 284c9ec08..7ad8780eb 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -24,7 +24,7 @@ bool is_future_output_enabled(grib_handle* h) { size_t step_output_format_size = 128; char step_output_format[step_output_format_size]; int ret = 0; - if ((ret = grib_get_string_internal(h, "step_output_format", step_output_format, &step_output_format_size)) != GRIB_SUCCESS) + if ((ret = grib_get_string_internal(h, "stepOutputFormat", step_output_format, &step_output_format_size)) != GRIB_SUCCESS) return ret; return strcmp(step_output_format, "future") == 0; } From 037fdbbddc8478a8c10e6cd6ff9781d22c5a88bf Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 25 Aug 2023 09:04:42 +0000 Subject: [PATCH 020/125] ECC-1620: Bug fix --- src/grib_accessor_class_step_in_units.cc | 2 ++ tests/grib_ecc-1620.sh | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 27d33e627..6b5bd4656 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -375,5 +375,7 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) Step step(value_secs, Unit::SECOND); step.set_unit(step_units_old); *val = step.value(); + if ((ret = grib_set_long_internal(h, "stepUnits", step_units_old)) != GRIB_SUCCESS) + return ret; return GRIB_SUCCESS; } diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 261f4bc13..048bb26de 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -115,7 +115,6 @@ 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 @@ -145,13 +144,13 @@ 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_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 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_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 From 1f268a57c63a1099a6cf4b5067ffa5e654df6293 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 25 Aug 2023 09:16:19 +0000 Subject: [PATCH 021/125] ECC-1620: Bug fix (MARS output) --- src/step.cc | 29 +++++++++--------- src/step.h | 87 ++++++++++++++++++++++++++--------------------------- 2 files changed, 56 insertions(+), 60 deletions(-) diff --git a/src/step.cc b/src/step.cc index 21b5929ee..1a8c709f8 100644 --- a/src/step.cc +++ b/src/step.cc @@ -166,21 +166,20 @@ Step& Step::optimize_unit() { unit_ = internal_unit_; Seconds duration(0); switch (internal_unit_.to_value()) { - 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; + case Unit::SECOND: duration = Seconds(internal_value_); break; + case Unit::MINUTE: duration = Minutes(internal_value_); break; + case Unit::MINUTES15: duration = Minutes15(internal_value_); break; + case Unit::MINUTES30: duration = Minutes30(internal_value_); break; + case Unit::HOUR: duration = Hours(internal_value_); break; + case Unit::HOURS3: duration = Hours3(internal_value_); break; + case Unit::HOURS6: duration = Hours6(internal_value_); break; + case Unit::HOURS12: duration = Hours12(internal_value_); break; + case Unit::DAY: duration = Days(internal_value_); break; + case Unit::MONTH: duration = Months(internal_value_); break; + case Unit::YEAR: duration = Years(internal_value_); break; + case Unit::YEARS10: duration = Years10(internal_value_); break; + case Unit::YEARS30: duration = Years30(internal_value_); break; + case Unit::CENTURY: duration = Centuries(internal_value_); break; default: std::string msg = "Unknown unit: " + internal_unit_.to_string(); throw std::runtime_error(msg); diff --git a/src/step.h b/src/step.h index a39daf989..f07ee5412 100644 --- a/src/step.h +++ b/src/step.h @@ -224,21 +224,20 @@ private: Seconds secs(0); switch (internal_unit_.to_value()) { - 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; + case Unit::SECOND: secs = Seconds(internal_value_); break; + case Unit::MINUTE: secs = Minutes(internal_value_); break; + case Unit::MINUTES15: secs = Minutes15(internal_value_); break; + case Unit::MINUTES30: secs = Minutes30(internal_value_); break; + case Unit::HOUR: secs = Hours(internal_value_); break; + case Unit::HOURS3: secs = Hours3(internal_value_); break; + case Unit::HOURS6: secs = Hours6(internal_value_); break; + case Unit::HOURS12: secs = Hours12(internal_value_); break; + case Unit::DAY: secs = Days(internal_value_); break; + case Unit::MONTH: secs = Months(internal_value_); break; + case Unit::YEAR: secs = Years(internal_value_); break; + case Unit::YEARS10: secs = Years10(internal_value_); break; + case Unit::YEARS30: secs = Years30(internal_value_); break; + case Unit::CENTURY: secs = Centuries(internal_value_); break; default: std::string msg = "Unknown unit: " + internal_unit_.to_string(); throw std::runtime_error(msg); @@ -271,21 +270,20 @@ template T Step::value() const { } Seconds duration(0); switch (internal_unit_.to_value()) { - 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; + case Unit::SECOND: duration = Seconds(internal_value_); break; + case Unit::MINUTE: duration = Minutes(internal_value_); break; + case Unit::MINUTES15: duration = Minutes15(internal_value_); break; + case Unit::MINUTES30: duration = Minutes30(internal_value_); break; + case Unit::HOUR: duration = Hours(internal_value_); break; + case Unit::HOURS3: duration = Hours3(internal_value_); break; + case Unit::HOURS6: duration = Hours6(internal_value_); break; + case Unit::HOURS12: duration = Hours12(internal_value_); break; + case Unit::DAY: duration = Days(internal_value_); break; + case Unit::MONTH: duration = Months(internal_value_); break; + case Unit::YEAR: duration = Years(internal_value_); break; + case Unit::YEARS10: duration = Years10(internal_value_); break; + case Unit::YEARS30: duration = Years30(internal_value_); break; + case Unit::CENTURY: duration = Centuries(internal_value_); break; default: std::string msg = "Unknown unit: " + internal_unit_.to_string(); throw std::runtime_error(msg); @@ -293,21 +291,20 @@ template T Step::value() const { T value = 0; switch (unit_.to_value()) { - case Unit::SECOND: - value = duration.count(); - break; - case Unit::MINUTE: - value = std::chrono::duration_cast>(duration).count(); - break; - case Unit::HOUR: - value = std::chrono::duration_cast>(duration).count(); - break; - case Unit::DAY: - value = std::chrono::duration_cast>(duration).count(); - break; - case Unit::MONTH: - value = std::chrono::duration_cast>(duration).count(); - break; + case Unit::SECOND: value = duration.count(); break; + case Unit::MINUTE: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::MINUTES15: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::MINUTES30: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::HOUR: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::HOURS3: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::HOURS6: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::HOURS12: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::DAY: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::MONTH: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::YEAR: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::YEARS10: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::YEARS30: value = std::chrono::duration_cast>(duration).count(); break; + case Unit::CENTURY: value = std::chrono::duration_cast>(duration).count(); break; default: std::string msg = "Unknown unit: " + UnitType{unit_}.to_string(); throw std::runtime_error(msg); From febbca0c3f094e27dc373ea549242f26a82f14e7 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 30 Aug 2023 06:00:49 +0000 Subject: [PATCH 022/125] ECC-1620: Remove double packing and unpacking --- .../grib2/template.4.forecast_time.def | 1 + src/grib_accessor_class_g2end_step.cc | 74 ++------ src/grib_accessor_class_g2step_range.cc | 43 +---- src/grib_accessor_class_optimal_step_units.cc | 13 +- src/grib_accessor_class_step_in_units.cc | 128 +++++-------- src/step.cc | 172 ++++++++---------- src/step.h | 164 +++++++++-------- src/step_utilities.cc | 21 ++- src/step_utilities.h | 23 +++ tests/grib_ecc-1620.sh | 90 ++++----- 10 files changed, 319 insertions(+), 410 deletions(-) diff --git a/definitions/grib2/template.4.forecast_time.def b/definitions/grib2/template.4.forecast_time.def index 00df0b1a2..600be0616 100644 --- a/definitions/grib2/template.4.forecast_time.def +++ b/definitions/grib2/template.4.forecast_time.def @@ -14,6 +14,7 @@ codetable[1] indicatorOfUnitOfTimeRange ('4.4.table',masterDir,localDir) : dump #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; +transient useOptimalStepUnits = 0; meta stepUnits optimal_step_units(forecastTime,indicatorOfUnitOfTimeRange,lengthOfTimeRange,indicatorOfUnitForTimeRange) : dump; # Forecast time in units defined by previous octet (GRIB-29: supports negative forecast time) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index b8ab3b411..836f42825 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -20,7 +20,6 @@ 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 @@ -59,10 +58,8 @@ or edit "accessor.class" and rerun ./make_class.pl */ -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 void dump(grib_accessor*, grib_dumper*); @@ -117,9 +114,9 @@ static grib_accessor_class _grib_accessor_class_g2end_step = { 0, /* is_missing */ &pack_long, /* pack_long */ &unpack_long, /* unpack_long */ - &pack_double, /* pack_double */ + 0, /* pack_double */ 0, /* pack_float */ - &unpack_double, /* unpack_double */ + 0, /* unpack_double */ 0, /* unpack_float */ &pack_string, /* pack_string */ &unpack_string, /* unpack_string */ @@ -233,7 +230,7 @@ static int is_special_expver(grib_handle* h) return 0; } -static int convert_time_range( +static int convert_time_range_long_( grib_handle* h, long stepUnits, /* unit */ long indicatorOfUnitForTimeRange, /* coded_unit */ @@ -269,7 +266,8 @@ static int convert_time_range( return GRIB_SUCCESS; } -static int unpack_one_time_range(grib_accessor* a, long* val, size_t* len) + +static int unpack_one_time_range_long_(grib_accessor* a, long* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; int err = 0; @@ -292,7 +290,7 @@ static int unpack_one_time_range(grib_accessor* a, long* val, size_t* len) if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement))) return err; - err = convert_time_range(h, unit, coded_unit, &coded_time_range); + err = convert_time_range_long_(h, unit, coded_unit, &coded_time_range); if (err != GRIB_SUCCESS) return err; @@ -314,8 +312,9 @@ static int unpack_one_time_range(grib_accessor* a, long* val, size_t* len) return GRIB_SUCCESS; } + #define MAX_NUM_TIME_RANGES 16 /* maximum number of time range specifications */ -static int unpack_multiple_time_ranges(grib_accessor* a, long* val, size_t* len) +static int unpack_multiple_time_ranges_long_(grib_accessor* a, long* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; int i = 0, err = 0; @@ -354,7 +353,7 @@ static int unpack_multiple_time_ranges(grib_accessor* a, long* val, size_t* len) long the_coded_unit = arr_coded_unit[i]; long the_coded_time_range = arr_coded_time_range[i]; - err = convert_time_range(h, unit, the_coded_unit, &the_coded_time_range); + err = convert_time_range_long_(h, unit, the_coded_unit, &the_coded_time_range); if (err != GRIB_SUCCESS) return err; @@ -368,6 +367,7 @@ static int unpack_multiple_time_ranges(grib_accessor* a, long* val, size_t* len) return GRIB_DECODING_ERROR; } + // For the old implementation of unpack_long, see // src/deprecated/grib_accessor_class_g2end_step.unpack_long.cc // @@ -394,18 +394,19 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) Assert(numberOfTimeRange == 1 || numberOfTimeRange == 2); if (numberOfTimeRange == 1) { - ret = unpack_one_time_range(a, val, len); + ret = unpack_one_time_range_long_(a, val, len); return ret; } else { - ret = unpack_multiple_time_ranges(a, val, len); + ret = unpack_multiple_time_ranges_long_(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; @@ -513,6 +514,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return GRIB_SUCCESS; } + static int unpack_string(grib_accessor* a, char* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; @@ -550,29 +552,6 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) } -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.optimize_unit(); - if ((ret = grib_set_long_internal(h, "stepUnits", end_step.unit().to_long())) != 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_string(grib_accessor* a, const char* val, size_t* len) { //grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; @@ -583,29 +562,10 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) if ((ret = grib_set_long_internal(h, "stepUnits", end_step.unit().to_long())) != GRIB_SUCCESS) return ret; - double end_step_value = end_step.value(); + long 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) + if ((ret = pack_long(a, &end_step_value, &end_step_len)) != GRIB_SUCCESS) return ret; return GRIB_SUCCESS; } - - -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 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; - - 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 05bf65be7..a6291b646 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -24,7 +24,6 @@ SUPER = grib_accessor_class_gen IMPLEMENTS = pack_string;unpack_string;value_count IMPLEMENTS = unpack_long;pack_long - IMPLEMENTS = unpack_double;pack_double IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = get_native_type;string_length IMPLEMENTS = init @@ -45,10 +44,8 @@ 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*); @@ -87,9 +84,9 @@ static grib_accessor_class _grib_accessor_class_g2step_range = { 0, /* is_missing */ &pack_long, /* pack_long */ &unpack_long, /* unpack_long */ - &pack_double, /* pack_double */ + 0, /* pack_double */ 0, /* pack_float */ - &unpack_double, /* unpack_double */ + 0, /* unpack_double */ 0, /* unpack_float */ &pack_string, /* pack_string */ &unpack_string, /* unpack_string */ @@ -249,42 +246,6 @@ 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.hide_hour_unit(); - 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; -} static int unpack_long(grib_accessor* a, long* val, size_t* len) { diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index e670034c6..79d9cf054 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -167,17 +167,18 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - auto start_step_opt = get_step(h, self->forecastTime, self->indicatorOfUnitOfTimeRange); - auto end_step_opt = get_step(h, self->lengthOfTimeRange, self->indicatorOfUnitForTimeRange); + auto forecast_time_opt = get_step(h, self->forecastTime, self->indicatorOfUnitOfTimeRange); + auto lenght_of_time_range_opt = get_step(h, self->lengthOfTimeRange, self->indicatorOfUnitForTimeRange); - if (!(start_step_opt && end_step_opt)) { + if (!(forecast_time_opt && lenght_of_time_range_opt)) { *val = UnitType{Unit::HOUR}.to_long(); + return GRIB_SUCCESS; } - Step start_step = start_step_opt.value_or(Step{}); - Step end_step = end_step_opt.value_or(Step{}); + Step forecast_time = forecast_time_opt.value_or(Step{}); + Step length_of_time_range = lenght_of_time_range_opt.value_or(Step{}); - auto [step_a, step_b] = find_common_units(start_step.optimize_unit(), end_step.optimize_unit()); + auto [step_a, step_b] = find_common_units(forecast_time.optimize_unit(), (forecast_time + length_of_time_range).optimize_unit()); *val = step_a.unit().to_long(); return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 6b5bd4656..89c23b130 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -19,7 +19,6 @@ 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 @@ -42,10 +41,8 @@ or edit "accessor.class" and rerun ./make_class.pl */ -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 void dump(grib_accessor*, grib_dumper*); @@ -87,9 +84,9 @@ static grib_accessor_class _grib_accessor_class_step_in_units = { 0, /* is_missing */ &pack_long, /* pack_long */ &unpack_long, /* unpack_long */ - &pack_double, /* pack_double */ + 0, /* pack_double */ 0, /* pack_float */ - &unpack_double, /* unpack_double */ + 0, /* unpack_double */ 0, /* unpack_float */ &pack_string, /* pack_string */ &unpack_string, /* unpack_string */ @@ -174,23 +171,23 @@ static const int u2s[] = { 1800 /* (15) 30 minutes */ }; + static int unpack_long(grib_accessor* a, 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; - + int err = 0; long codedStep, codedUnits, stepUnits; + grib_handle* h = grib_handle_of_accessor(a); int factor = 0; long u2sf, u2sf_step_unit; - 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 ((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 (stepUnits != codedUnits) { *val = codedStep * u2s2[codedUnits]; @@ -209,9 +206,9 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) } if (*val % u2sf_step_unit != 0) { - ret = grib_set_long_internal(h, self->stepUnits, codedUnits); + err = grib_set_long_internal(h, self->stepUnits, codedUnits); *val = codedStep; - return ret; + return err; } *val = *val / u2sf_step_unit; } @@ -221,11 +218,11 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) return GRIB_SUCCESS; } + 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 err = 0; long codedStep, codedUnits, stepUnits; long oldStep = 0; @@ -275,21 +272,36 @@ 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) { grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); int ret = 0; + size_t value_len = 0; Step step = step_from_string(val); - step.optimize_unit(); + long step_units; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + return ret; - if ((ret = grib_set_long_internal(h, self->stepUnits, step.unit().to_long()))) + long end_step_value; + if ((ret = grib_get_long_internal(h, "endStep", &end_step_value)) != GRIB_SUCCESS) return ret; - long step_value = step.value(); - if ((ret = pack_long(a, &step_value, len)) != GRIB_SUCCESS) + Step end_step{end_step_value, UnitType{step_units}}; + + auto [step_a, step_b] = find_common_units(step, end_step); + if ((ret = grib_set_long_internal(h, "stepUnits", step_a.unit().to_long())) != GRIB_SUCCESS) return ret; + long value = step.value(step_a.unit()); + + if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS) + return ret; + + //if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS) + //return ret; + return GRIB_SUCCESS; } @@ -298,84 +310,26 @@ 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; - - long step_units_old; - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_old)) != GRIB_SUCCESS) + long value; + size_t value_len; + if ((ret = unpack_long(a, &value, &value_len)) != GRIB_SUCCESS) return ret; - if ((ret = grib_set_long_internal(h, "stepUnits", UnitType{Unit::SECOND}.to_long())) != 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.set_unit(step_units_old); - - if ((ret = grib_set_long_internal(h, "stepUnits", step_units_old)) != GRIB_SUCCESS) + long step_units; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; + Step step{value, step_units}; step.hide_hour_unit(); + //snprintf(val, *len, "%ld", value); + if (is_future_output_enabled(h)) { snprintf(val, *len, "%s", step.to_string().c_str()); } else { snprintf(val, *len, "%ld", step.value()); } - return GRIB_SUCCESS; } -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 step_units; - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) - return ret; - Step start_step{*val, step_units}; - - start_step.optimize_unit(); - if ((ret = grib_set_long_internal(h, "stepUnits", start_step.unit().to_long())) != GRIB_SUCCESS) - return ret; - long start_step_value = start_step.value(); - - if ((ret = pack_long(a, &start_step_value, len)) != GRIB_SUCCESS) - return ret; - - 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}.to_long())) != 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.set_unit(step_units_old); - *val = step.value(); - if ((ret = grib_set_long_internal(h, "stepUnits", step_units_old)) != GRIB_SUCCESS) - return ret; - return GRIB_SUCCESS; -} diff --git a/src/step.cc b/src/step.cc index 1a8c709f8..13ff22cd8 100644 --- a/src/step.cc +++ b/src/step.cc @@ -12,14 +12,35 @@ UnitType::Map UnitType::map_{}; -std::vector UnitType::unitOrder = { - Unit::SECOND, - Unit::MINUTE, - Unit::HOUR, - }; + +std::vector UnitType::unit_order_ = { + Unit::SECOND, + Unit::MINUTE, + Unit::HOUR, + //Unit::DAY, +}; + +std::vector UnitType::complete_unit_order_ = { + Unit::MISSING , + Unit::SECOND , + Unit::MINUTE , + Unit::MINUTES15 , + Unit::MINUTES30 , + Unit::HOUR , + Unit::HOURS3 , + Unit::HOURS6 , + Unit::HOURS12 , + Unit::DAY , + Unit::MONTH , + Unit::YEAR , + Unit::YEARS10 , + Unit::YEARS30 , + Unit::CENTURY +}; -Step step_from_string(std::string step) { +Step step_from_string(std::string step) +{ std::regex re("([0-9.]+)([smhDMYC]?)"); std::smatch match; if (std::regex_match(step, match, re)) { @@ -35,7 +56,9 @@ Step step_from_string(std::string step) { throw std::runtime_error("Could not parse step: " + step); } -std::vector parse_range(const std::string& range_str) { + +std::vector parse_range(const std::string& range_str) +{ std::vector steps; std::string::size_type pos = 0; std::string::size_type prev = 0; @@ -48,31 +71,52 @@ std::vector parse_range(const std::string& range_str) { } -bool Step::operator==(const Step& other) const { +bool Step::operator==(const Step& other) const +{ if ((internal_value_ == other.internal_value_) && (internal_unit_ == other.internal_unit_)) { return true; } return false; } -Step Step::operator+(const Step& step) { + +bool Step::operator>(const Step& step) const +{ + auto [a, b] = find_common_units(this->copy().optimize_unit(), step.copy().optimize_unit()); + assert(a.internal_unit_ == b.internal_unit_); + return a.internal_value_ > b.internal_value_; +} + + +bool Step::operator<(const Step& step) const +{ + auto [a, b] = find_common_units(this->copy().optimize_unit(), step.copy().optimize_unit()); + assert(a.internal_unit_ == b.internal_unit_); + return a.internal_value_ < b.internal_value_; +} + + +Step Step::operator+(const Step& step) const +{ Step tmp = step; - auto [a, b] = find_common_units(this->optimize_unit(), tmp.optimize_unit()); + auto [a, b] = find_common_units(this->copy().optimize_unit(), tmp.copy().optimize_unit()); assert(a.internal_unit_ == b.internal_unit_); return Step(a.internal_value_ + b.internal_value_, a.internal_unit_); } -Step Step::operator-(const Step& step) { + +Step Step::operator-(const Step& step) const +{ Step tmp = step; - auto [a, b] = find_common_units(this->optimize_unit(), tmp.optimize_unit()); + auto [a, b] = find_common_units(this->copy().optimize_unit(), tmp.copy().optimize_unit()); 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_); } -std::pair find_common_units(const Step& startStep, const Step& endStep) { + +//std::pair find_common_units(const Step& startStep, const Step& endStep) +std::pair find_common_units(const Step& startStep, const Step& endStep) +{ Step a = startStep; Step b = endStep; @@ -97,11 +141,11 @@ std::pair find_common_units(const Step& startStep, const Step& endSt } else { // Find the highest common unit - auto it = std::find_if(UnitType::unitOrder.begin(), UnitType::unitOrder.end(), [&](const auto& e) { + auto it = std::find_if(UnitType::unit_order_.begin(), UnitType::unit_order_.end(), [&](const auto& e) { return e == a.unit().to_value() || e == b.unit().to_value(); }); - assert(it != UnitType::unitOrder.end()); + assert(it != UnitType::unit_order_.end()); a.set_unit(*it); b.set_unit(*it); @@ -113,84 +157,43 @@ std::pair find_common_units(const Step& startStep, const Step& endSt return {a, b}; } -void Step::sanity_check() const { +void Step::sanity_check() 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."); - } + //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::init_long(long value, const UnitType& unit) { +void Step::init_long(long value, const UnitType& unit) +{ internal_value_ = value; internal_unit_ = unit; unit_ = internal_unit_; sanity_check(); } -void Step::init_double(double value, const UnitType& unit) { +void Step::init_double(double value, const UnitType& unit) +{ long seconds = UnitType::get_converter().unit_to_duration(unit.to_value()); init_long(static_cast(value * seconds), UnitType{Unit::SECOND}); optimize_unit(); } -Step::Step(double value, const UnitType& unit) : internal_unit_{unit}, unit_{internal_unit_} {init_double(value, unit);} -Step::Step(double value, Unit unit) {init_double(value, UnitType{unit});} -Step::Step(double value, long unit) {init_double(value, UnitType{unit});} -Step::Step(double value, const std::string& unit) {init_double(value, UnitType{unit});} - -Step::Step(long value, const UnitType& unit) { init_long(value, unit);} -Step::Step(long value, Unit unit) {init_long(value, UnitType{unit});} -Step::Step(long value, long unit) {init_long(value, UnitType{unit});} -Step::Step(long value, const std::string& unit) {init_long(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); - - init_double(v, UnitType{u_str}); -} - - -Step& Step::optimize_unit() { +Step& Step::optimize_unit() +{ if (internal_value_ == 0) { return *this; } unit_ = internal_unit_; - Seconds duration(0); - switch (internal_unit_.to_value()) { - case Unit::SECOND: duration = Seconds(internal_value_); break; - case Unit::MINUTE: duration = Minutes(internal_value_); break; - case Unit::MINUTES15: duration = Minutes15(internal_value_); break; - case Unit::MINUTES30: duration = Minutes30(internal_value_); break; - case Unit::HOUR: duration = Hours(internal_value_); break; - case Unit::HOURS3: duration = Hours3(internal_value_); break; - case Unit::HOURS6: duration = Hours6(internal_value_); break; - case Unit::HOURS12: duration = Hours12(internal_value_); break; - case Unit::DAY: duration = Days(internal_value_); break; - case Unit::MONTH: duration = Months(internal_value_); break; - case Unit::YEAR: duration = Years(internal_value_); break; - case Unit::YEARS10: duration = Years10(internal_value_); break; - case Unit::YEARS30: duration = Years30(internal_value_); break; - case Unit::CENTURY: duration = Centuries(internal_value_); break; - default: - std::string msg = "Unknown unit: " + internal_unit_.to_string(); - throw std::runtime_error(msg); - } + Seconds seconds = to_seconds(internal_value_, internal_unit_); - Seconds d = std::chrono::duration_cast>(duration); - - for (auto it = UnitType::unitOrder.rbegin(); it != UnitType::unitOrder.rend(); ++it) { + for (auto it = UnitType::unit_order_.rbegin(); it != UnitType::unit_order_.rend(); ++it) { long multiplier = UnitType::get_converter().unit_to_duration(*it); - if (d.count() % multiplier == 0) { - internal_value_ = duration.count() / multiplier; + if (seconds.count() % multiplier == 0) { + internal_value_ = seconds.count() / multiplier; internal_unit_ = *it; unit_ = *it; return *this; @@ -199,24 +202,3 @@ Step& Step::optimize_unit() { return *this; } - -Step& Step::set_unit(const std::string& unit_name) { - unit_ = UnitType{unit_name}; - return *this; -} - -Step& Step::set_unit(long unit_code) { - unit_ = UnitType{unit_code}; - return *this; -} - -Step& Step::set_unit(const UnitType& new_unit) { - unit_ = new_unit; - return *this; -} - -Step& Step::set_unit(const Unit new_unit) { - unit_ = new_unit; - return *this; -} - diff --git a/src/step.h b/src/step.h index f07ee5412..a5d6d5343 100644 --- a/src/step.h +++ b/src/step.h @@ -32,7 +32,6 @@ template using Minutes15 = std::chrono::duration template using Minutes30 = std::chrono::duration>; template using Missing = std::chrono::duration>; - enum class Unit { MINUTE = 0, HOUR = 1, @@ -51,10 +50,13 @@ enum class Unit { MISSING = 255, }; +class UnitType; +template Seconds to_seconds(long value, const UnitType& unit); +template T from_seconds(Seconds seconds, const UnitType& unit); class UnitType { public: - explicit UnitType() : internal_value_(Unit::HOUR) {} + 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);} @@ -82,7 +84,8 @@ public: Unit to_value() const {return internal_value_;} void hide_hour_unit() {hide_hour_unit_ = true;} void show_hour_unit() {hide_hour_unit_ = false;} - static std::vector unitOrder; + static std::vector unit_order_; + static std::vector complete_unit_order_; private: bool hide_hour_unit_ = false; @@ -163,42 +166,46 @@ class Step { public: // Constructors 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); + Step(double value, const UnitType& unit) : internal_unit_{unit}, unit_{internal_unit_} {init_double(value, unit);} + Step(double value, Unit unit) {init_double(value, UnitType{unit});} + Step(double value, long unit) {init_double(value, UnitType{unit});} + Step(double value, const std::string& unit) {init_double(value, UnitType{unit});} + + Step(long value, const UnitType& unit) { init_long(value, unit);} + Step(long value, Unit unit) {init_long(value, UnitType{unit});} + Step(long value, long unit) {init_long(value, UnitType{unit});} + Step(long value, const std::string& unit) {init_long(value, UnitType{unit});} // Getters template T value() const; + template T value(const UnitType& unit) const; UnitType unit() const { return unit_; } // Setters - Step& set_unit(long new_unit); - Step& set_unit(const std::string& new_unit); - Step& set_unit(const Unit new_unit); - Step& set_unit(const UnitType& new_unit); + Step& set_unit(const std::string& unit_name) {unit_ = UnitType{unit_name}; return *this;} + Step& set_unit(long unit_code) {unit_ = UnitType{unit_code}; return *this;} + Step& set_unit(const UnitType& new_unit) {unit_ = new_unit; return *this;} + Step& set_unit(const Unit new_unit) {unit_ = new_unit; return *this;} // Operators bool operator==(const Step& other) const; bool operator!=(const Step& other) const; - Step operator+(const Step& step); - Step operator-(const Step& step); + Step operator+(const Step& step) const; + Step operator-(const Step& step) const; + bool operator>(const Step& step) const; + bool operator<(const Step& step) const; + Step copy() const {return Step{internal_value_, internal_unit_};} // Methods Step& optimize_unit(); friend std::pair find_common_units(const Step& startStep, const Step& endStep); void hide_hour_unit() { - internal_unit_.hide_hour_unit(); + internal_unit_.hide_hour_unit(); unit_.hide_hour_unit(); } void show_hour_unit() { - internal_unit_.show_hour_unit(); + internal_unit_.show_hour_unit(); unit_.show_hour_unit(); } @@ -222,29 +229,9 @@ private: return *this; } - Seconds secs(0); - switch (internal_unit_.to_value()) { - case Unit::SECOND: secs = Seconds(internal_value_); break; - case Unit::MINUTE: secs = Minutes(internal_value_); break; - case Unit::MINUTES15: secs = Minutes15(internal_value_); break; - case Unit::MINUTES30: secs = Minutes30(internal_value_); break; - case Unit::HOUR: secs = Hours(internal_value_); break; - case Unit::HOURS3: secs = Hours3(internal_value_); break; - case Unit::HOURS6: secs = Hours6(internal_value_); break; - case Unit::HOURS12: secs = Hours12(internal_value_); break; - case Unit::DAY: secs = Days(internal_value_); break; - case Unit::MONTH: secs = Months(internal_value_); break; - case Unit::YEAR: secs = Years(internal_value_); break; - case Unit::YEARS10: secs = Years10(internal_value_); break; - case Unit::YEARS30: secs = Years30(internal_value_); break; - case Unit::CENTURY: secs = Centuries(internal_value_); break; - default: - std::string msg = "Unknown unit: " + internal_unit_.to_string(); - throw std::runtime_error(msg); - } - + Seconds seconds = to_seconds(internal_value_, internal_unit_); long multiplier = UnitType::get_converter().unit_to_duration(unit_.to_value()); - internal_value_ = secs.count() / multiplier; + internal_value_ = seconds.count() / multiplier; internal_unit_ = unit_; return *this; @@ -263,50 +250,75 @@ std::pair find_common_units(const Step& startStep, const Step& endSt template T Step::value() const { if (internal_value_ == 0) { - return internal_value_; + return 0; } if (internal_unit_ == unit_) { return internal_value_; } - Seconds duration(0); - switch (internal_unit_.to_value()) { - case Unit::SECOND: duration = Seconds(internal_value_); break; - case Unit::MINUTE: duration = Minutes(internal_value_); break; - case Unit::MINUTES15: duration = Minutes15(internal_value_); break; - case Unit::MINUTES30: duration = Minutes30(internal_value_); break; - case Unit::HOUR: duration = Hours(internal_value_); break; - case Unit::HOURS3: duration = Hours3(internal_value_); break; - case Unit::HOURS6: duration = Hours6(internal_value_); break; - case Unit::HOURS12: duration = Hours12(internal_value_); break; - case Unit::DAY: duration = Days(internal_value_); break; - case Unit::MONTH: duration = Months(internal_value_); break; - case Unit::YEAR: duration = Years(internal_value_); break; - case Unit::YEARS10: duration = Years10(internal_value_); break; - case Unit::YEARS30: duration = Years30(internal_value_); break; - case Unit::CENTURY: duration = Centuries(internal_value_); break; + Seconds seconds = to_seconds(internal_value_, internal_unit_); + T value = from_seconds(seconds, unit_); + return value; +} + +template T Step::value(const UnitType& unit) const { + if (internal_value_ == 0) { + return 0; + } + if (internal_unit_ == unit) { + return internal_value_; + } + Seconds seconds = to_seconds(internal_value_, internal_unit_); + T value = from_seconds(seconds, unit); + return value; +} + + +template +Seconds to_seconds(long value, const UnitType& unit) { + Seconds seconds; + switch (unit.to_value()) { + case Unit::SECOND: seconds = Seconds(value); break; + case Unit::MINUTE: seconds = Minutes(value); break; + case Unit::MINUTES15: seconds = Minutes15(value); break; + case Unit::MINUTES30: seconds = Minutes30(value); break; + case Unit::HOUR: seconds = Hours(value); break; + case Unit::HOURS3: seconds = Hours3(value); break; + case Unit::HOURS6: seconds = Hours6(value); break; + case Unit::HOURS12: seconds = Hours12(value); break; + case Unit::DAY: seconds = Days(value); break; + case Unit::MONTH: seconds = Months(value); break; + case Unit::YEAR: seconds = Years(value); break; + case Unit::YEARS10: seconds = Years10(value); break; + case Unit::YEARS30: seconds = Years30(value); break; + case Unit::CENTURY: seconds = Centuries(value); break; default: - std::string msg = "Unknown unit: " + internal_unit_.to_string(); + std::string msg = "Unknown unit: " + unit.to_string(); throw std::runtime_error(msg); } + return seconds; +} + +template +T from_seconds(Seconds seconds, const UnitType& unit) { T value = 0; - switch (unit_.to_value()) { - case Unit::SECOND: value = duration.count(); break; - case Unit::MINUTE: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::MINUTES15: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::MINUTES30: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::HOUR: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::HOURS3: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::HOURS6: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::HOURS12: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::DAY: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::MONTH: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::YEAR: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::YEARS10: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::YEARS30: value = std::chrono::duration_cast>(duration).count(); break; - case Unit::CENTURY: value = std::chrono::duration_cast>(duration).count(); break; + switch (unit.to_value()) { + case Unit::SECOND: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::MINUTE: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::MINUTES15: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::MINUTES30: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::HOUR: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::HOURS3: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::HOURS6: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::HOURS12: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::DAY: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::MONTH: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::YEAR: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::YEARS10: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::YEARS30: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::CENTURY: value = std::chrono::duration_cast>(seconds).count(); break; default: - std::string msg = "Unknown unit: " + UnitType{unit_}.to_string(); + std::string msg = "Unknown unit: " + unit.to_string(); throw std::runtime_error(msg); } return value; diff --git a/src/step_utilities.cc b/src/step_utilities.cc index 7ad8780eb..808010bcb 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -1,8 +1,9 @@ -//#include "step_range.h" #include "step_utilities.h" +#include -std::optional get_step(grib_handle* h, const std::string& value_key, const std::string& unit_key){ +std::optional get_step(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) @@ -20,7 +21,21 @@ std::optional get_step(grib_handle* h, const std::string& value_key, const } -bool is_future_output_enabled(grib_handle* h) { +int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step) +{ + int err; + Step step_copy = step.copy(); + step_copy.optimize_unit(); + if ((err = grib_set_long_internal(h, value_key.c_str(), step_copy.value())) != GRIB_SUCCESS) + return err; + if ((err = grib_set_long_internal(h, unit_key.c_str(), step_copy.unit().to_long())) != GRIB_SUCCESS) + return err; + return GRIB_SUCCESS; +} + + +bool is_future_output_enabled(grib_handle* h) +{ size_t step_output_format_size = 128; char step_output_format[step_output_format_size]; int ret = 0; diff --git a/src/step_utilities.h b/src/step_utilities.h index d6733e0e4..65176a76c 100644 --- a/src/step_utilities.h +++ b/src/step_utilities.h @@ -6,4 +6,27 @@ std::optional get_step(grib_handle* h, const std::string& value_key, const std::string& unit_key); bool is_future_output_enabled(grib_handle* h); +int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step); + +//template +//int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step) +//{ +// int err; +// if constexpr (std::is_same_v) { +// if ((err = grib_set_long_internal(h, value_key.c_str(), step.value())) != GRIB_SUCCESS) +// return err; +// } +// else if constexpr (std::is_same_v) { +// if ((err = grib_set_double_internal(h, value_key.c_str(), step.value())) != GRIB_SUCCESS) +// return err; +// } +// else { +// return GRIB_NOT_IMPLEMENTED; +// } + +// if ((err = grib_set_long_internal(h, unit_key.c_str(), step.unit().to_long())) != GRIB_SUCCESS) +// return err; +// return GRIB_SUCCESS; +//} + diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 048bb26de..8700b086b 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -46,7 +46,7 @@ temp2=temp_2.$label -### CHECK: grib_set - endStep + stepUnits +#### 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 @@ -55,36 +55,36 @@ 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" +#${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=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=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" +#${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=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=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" @@ -92,44 +92,44 @@ 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=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=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=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=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=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" +#${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" -#${tools_dir}/grib_set -s $fn $temp +##${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" +##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 +##${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 @@ -147,13 +147,13 @@ 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_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 +#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 @@ -179,7 +179,7 @@ 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 "-y -p $keys_s" "0" 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" From 32b65a142feb28f8e1c8c8c0c512cfa533aff167 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 30 Aug 2023 08:52:27 +0000 Subject: [PATCH 023/125] ECC-1620: nai --- src/grib_accessor_class_step_in_units.cc | 42 ++++++++++++---- tests/grib_ecc-1620.sh | 61 +++++++++++++----------- 2 files changed, 66 insertions(+), 37 deletions(-) diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 89c23b130..598015bd1 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -233,6 +233,8 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits))) return err; + + unpack_long(a, &oldStep, len); if (stepUnits != codedUnits) { @@ -264,9 +266,18 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) else lengthOfTimeRange -= codedStep * u2s2[codedUnits] / u2s2[indicatorOfUnitForTimeRange]; lengthOfTimeRange = lengthOfTimeRange > 0 ? lengthOfTimeRange : 0; + + //lengthOfTimeRange = lengthOfTimeRange * u2s2[indicatorOfUnitForTimeRange] / u2s2[stepUnits]; + codedUnits = stepUnits; err = grib_set_long_internal(grib_handle_of_accessor(a), self->lengthOfTimeRange, lengthOfTimeRange); if (err != GRIB_SUCCESS) return err; + //err = grib_set_long_internal(grib_handle_of_accessor(a), self->indicatorOfUnitForTimeRange, codedUnits); + //if (err != GRIB_SUCCESS) + // return err; + //err = grib_set_long_internal(grib_handle_of_accessor(a), self->codedUnits, codedUnits); + //if (err != GRIB_SUCCESS) + // return err; } return grib_set_long_internal(grib_handle_of_accessor(a), self->codedStep, codedStep); @@ -285,16 +296,31 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; - long end_step_value; - if ((ret = grib_get_long_internal(h, "endStep", &end_step_value)) != GRIB_SUCCESS) - return ret; - Step end_step{end_step_value, UnitType{step_units}}; - auto [step_a, step_b] = find_common_units(step, end_step); - if ((ret = grib_set_long_internal(h, "stepUnits", step_a.unit().to_long())) != GRIB_SUCCESS) - return ret; - long value = step.value(step_a.unit()); + long value; + if (self->indicatorOfUnitForTimeRange != NULL) { + + long end_step_value; + if ((ret = grib_get_long_internal(h, "endStep", &end_step_value)) != GRIB_SUCCESS) + return ret; + Step end_step{end_step_value, UnitType{step_units}}; + + auto [step_a, step_b] = find_common_units(step, end_step); + if ((ret = grib_set_long_internal(h, "stepUnits", step_b.unit().to_long())) != GRIB_SUCCESS) + return ret; + + if ((ret = grib_set_long_internal(h, "endStep", step_b.value())) != GRIB_SUCCESS) + return ret; + + //if ((ret = set_step(h, self->lengthOfTimeRange, self->indicatorOfUnitForTimeRange, step_b)) != GRIB_SUCCESS) + //return ret; + + value = step.value(step_a.unit()); + } + else { + value = step.value(UnitType{step_units}); + } if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS) return ret; diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 8700b086b..3dc3583b7 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -92,44 +92,44 @@ 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=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=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=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=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=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" +${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" -##${tools_dir}/grib_set -s $fn $temp +#${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" +#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 +#${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 @@ -362,5 +362,8 @@ grib_check_key_equals $temp "-y -p $keys_d" "24 18 24" rm -f $temp +#~/build/eccodes/bin/grib_ls -m /perm/maro/referenceGRIBfiles4MTG2testing/grib1+2_operational_and_rd/151145_s2_enfo_cf_o2d_zos_2002_prod_ecmf_glob.grib2 +#~/build/eccodes/bin/grib_ls -m /perm/maro/referenceGRIBfiles4MTG2testing/grib1+2_operational_and_rd/240023_ce_efas_fc_sfc_dis06_2022_0001_ecmf_lisflood.grib2 + From b7019a99141f9682340226e88f978bfdcf2a497c Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 30 Aug 2023 09:33:37 +0000 Subject: [PATCH 024/125] ECC-1620: Workaround ECC-1676 --- src/grib_accessor_class_g2end_step.cc | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 836f42825..e42da9bda 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -521,25 +521,19 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - 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}.to_long())) != 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.set_unit(step_units_old); - - if ((ret = grib_set_long_internal(h, "stepUnits", step_units_old)) != GRIB_SUCCESS) + long step_units_old; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_old)) != GRIB_SUCCESS) return ret; + Step step(step_value, step_units_old); + step.set_unit(step_units_old); + step.hide_hour_unit(); if (is_future_output_enabled(h)) { snprintf(val, *len, "%s", step.to_string().c_str()); From 2786c982d42febcf251c000b7a442bdfebdf8b20 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 30 Aug 2023 10:16:33 +0000 Subject: [PATCH 025/125] ECC-1620: Refactoring --- src/grib_accessor_class_g2end_step.cc | 116 ++++++++--------- src/grib_accessor_class_g2step_range.cc | 64 ++++----- src/grib_accessor_class_optimal_step_units.cc | 34 ++--- src/grib_accessor_class_step_in_units.cc | 122 +++++++++--------- 4 files changed, 168 insertions(+), 168 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index e42da9bda..74987a952 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -22,8 +22,8 @@ IMPLEMENTS = unpack_long;pack_long IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = init;dump - MEMBERS = const char* start_step - MEMBERS = const char* unit + MEMBERS = const char* start_step_value // startStep + MEMBERS = const char* step_units // stepUnits MEMBERS = const char* year MEMBERS = const char* month @@ -39,8 +39,8 @@ MEMBERS = const char* minute_of_end_of_interval MEMBERS = const char* second_of_end_of_interval - MEMBERS = const char* coded_unit - MEMBERS = const char* coded_time_range + MEMBERS = const char* time_range_unit // indicatorOfUnitForTimeRange + MEMBERS = const char* time_range_value // lengthOfTimeRange MEMBERS = const char* typeOfTimeIncrement MEMBERS = const char* numberOfTimeRange @@ -71,8 +71,8 @@ typedef struct grib_accessor_g2end_step /* Members defined in gen */ /* Members defined in long */ /* Members defined in g2end_step */ - const char* start_step; - const char* unit; + const char* start_step_value; + const char* step_units; const char* year; const char* month; const char* day; @@ -85,8 +85,8 @@ typedef struct grib_accessor_g2end_step const char* hour_of_end_of_interval; const char* minute_of_end_of_interval; const char* second_of_end_of_interval; - const char* coded_unit; - const char* coded_time_range; + const char* time_range_unit; + const char* time_range_value; const char* typeOfTimeIncrement; const char* numberOfTimeRange; } grib_accessor_g2end_step; @@ -152,8 +152,8 @@ static void init(grib_accessor* a, const long l, grib_arguments* c) int n = 0; grib_handle* h = grib_handle_of_accessor(a); - self->start_step = grib_arguments_get_name(h, c, n++); - self->unit = grib_arguments_get_name(h, c, n++); + self->start_step_value = grib_arguments_get_name(h, c, n++); + self->step_units = grib_arguments_get_name(h, c, n++); self->year = grib_arguments_get_name(h, c, n++); self->month = grib_arguments_get_name(h, c, n++); @@ -169,8 +169,8 @@ static void init(grib_accessor* a, const long l, grib_arguments* c) self->minute_of_end_of_interval = grib_arguments_get_name(h, c, n++); self->second_of_end_of_interval = grib_arguments_get_name(h, c, n++); - self->coded_unit = grib_arguments_get_name(h, c, n++); - self->coded_time_range = grib_arguments_get_name(h, c, n++); + self->time_range_unit = grib_arguments_get_name(h, c, n++); + self->time_range_value = grib_arguments_get_name(h, c, n++); self->typeOfTimeIncrement = grib_arguments_get_name(h, c, n++); self->numberOfTimeRange = grib_arguments_get_name(h, c, n++); } @@ -232,9 +232,9 @@ static int is_special_expver(grib_handle* h) static int convert_time_range_long_( grib_handle* h, - long stepUnits, /* unit */ - long indicatorOfUnitForTimeRange, /* coded_unit */ - long* lengthOfTimeRange /* coded_time_range */ + long stepUnits, /* step_units */ + long indicatorOfUnitForTimeRange, /* time_range_unit */ + long* lengthOfTimeRange /* time_range_value */ ) { Assert(lengthOfTimeRange != NULL); @@ -271,26 +271,26 @@ static int unpack_one_time_range_long_(grib_accessor* a, long* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; int err = 0; - long start_step; - long unit; - long coded_unit; - long coded_time_range, typeOfTimeIncrement; + long start_step_value; + long step_units; + long time_range_unit; + long time_range_value, typeOfTimeIncrement; int add_time_range = 1; /* whether we add lengthOfTimeRange */ grib_handle* h = grib_handle_of_accessor(a); - if ((err = grib_get_long_internal(h, self->start_step, &start_step))) + if ((err = grib_get_long_internal(h, self->start_step_value, &start_step_value))) return err; - if ((err = grib_get_long_internal(h, self->unit, &unit))) + if ((err = grib_get_long_internal(h, self->step_units, &step_units))) return err; - if ((err = grib_get_long_internal(h, self->coded_unit, &coded_unit))) + if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) return err; - if ((err = grib_get_long_internal(h, self->coded_time_range, &coded_time_range))) + if ((err = grib_get_long_internal(h, self->time_range_value, &time_range_value))) return err; if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement))) return err; - err = convert_time_range_long_(h, unit, coded_unit, &coded_time_range); + err = convert_time_range_long_(h, step_units, time_range_unit, &time_range_value); if (err != GRIB_SUCCESS) return err; @@ -303,10 +303,10 @@ static int unpack_one_time_range_long_(grib_accessor* a, long* val, size_t* len) } } if (add_time_range) { - *val = start_step + coded_time_range; + *val = start_step_value + time_range_value; } else { - *val = start_step; + *val = start_step_value; } return GRIB_SUCCESS; @@ -319,16 +319,16 @@ static int unpack_multiple_time_ranges_long_(grib_accessor* a, long* val, size_t grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; int i = 0, err = 0; grib_handle* h = grib_handle_of_accessor(a); - long numberOfTimeRange = 0, unit = 0, start_step = 0; + long numberOfTimeRange = 0, step_units = 0, start_step_value = 0; size_t count = 0; long arr_typeOfTimeIncrement[MAX_NUM_TIME_RANGES] = {0,}; long arr_coded_unit[MAX_NUM_TIME_RANGES] = {0,}; long arr_coded_time_range[MAX_NUM_TIME_RANGES] = {0,}; - if ((err = grib_get_long_internal(h, self->start_step, &start_step))) + if ((err = grib_get_long_internal(h, self->start_step_value, &start_step_value))) return err; - if ((err = grib_get_long_internal(h, self->unit, &unit))) + if ((err = grib_get_long_internal(h, self->step_units, &step_units))) return err; if ((err = grib_get_long_internal(h, self->numberOfTimeRange, &numberOfTimeRange))) return err; @@ -341,9 +341,9 @@ static int unpack_multiple_time_ranges_long_(grib_accessor* a, long* val, size_t /* Get the arrays for the N time ranges */ if ((err = grib_get_long_array(h, self->typeOfTimeIncrement, arr_typeOfTimeIncrement, &count))) return err; - if ((err = grib_get_long_array(h, self->coded_unit, arr_coded_unit, &count))) + if ((err = grib_get_long_array(h, self->time_range_unit, arr_coded_unit, &count))) return err; - if ((err = grib_get_long_array(h, self->coded_time_range, arr_coded_time_range, &count))) + if ((err = grib_get_long_array(h, self->time_range_value, arr_coded_time_range, &count))) return err; /* Look in the array of typeOfTimeIncrements for first entry whose typeOfTimeIncrement == 2 */ @@ -353,11 +353,11 @@ static int unpack_multiple_time_ranges_long_(grib_accessor* a, long* val, size_t long the_coded_unit = arr_coded_unit[i]; long the_coded_time_range = arr_coded_time_range[i]; - err = convert_time_range_long_(h, unit, the_coded_unit, &the_coded_time_range); + err = convert_time_range_long_(h, step_units, the_coded_unit, &the_coded_time_range); if (err != GRIB_SUCCESS) return err; - *val = start_step + the_coded_time_range; + *val = start_step_value + the_coded_time_range; return GRIB_SUCCESS; } } @@ -376,15 +376,15 @@ 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; - long start_step; + long start_step_value; long numberOfTimeRange; - if ((ret = grib_get_long_internal(h, self->start_step, &start_step))) + if ((ret = grib_get_long_internal(h, self->start_step_value, &start_step_value))) return ret; /* point in time */ if (self->year == NULL) { - *val = start_step; + *val = start_step_value; return 0; } @@ -420,8 +420,8 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) long minute; long second; - long start_step; - long unit, coded_unit; + long start_step_value; + long step_units, time_range_unit; long year_of_end_of_interval; long month_of_end_of_interval; long day_of_end_of_interval; @@ -429,19 +429,19 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) long minute_of_end_of_interval = 0; long second_of_end_of_interval = 0; - long coded_time_range, time_range, typeOfTimeIncrement; + long time_range_value, time_range, typeOfTimeIncrement; double dend, dstep; /*point in time */ if (self->year == NULL) { - err = grib_set_long_internal(h, self->start_step, *val); + err = grib_set_long_internal(h, self->start_step_value, *val); return err; } - if ((err = grib_get_long_internal(h, self->coded_unit, &coded_unit))) + if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) return err; - if ((err = grib_get_long_internal(h, self->unit, &unit))) + if ((err = grib_get_long_internal(h, self->step_units, &step_units))) return err; if ((err = grib_get_long_internal(h, self->year, &year))) return err; @@ -456,16 +456,16 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) if ((err = grib_get_long_internal(h, self->second, &second))) return err; - if ((err = grib_get_long_internal(h, self->start_step, &start_step))) + if ((err = grib_get_long_internal(h, self->start_step_value, &start_step_value))) return err; if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement))) return err; - time_range = *val - start_step; + time_range = *val - start_step_value; if (time_range < 0) { grib_context_log(h->context, GRIB_LOG_ERROR, - "endStep < startStep (%ld < %ld)", *val, start_step); + "endStep < startStep (%ld < %ld)", *val, start_step_value); return GRIB_WRONG_STEP; } @@ -473,7 +473,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) if (err != GRIB_SUCCESS) return err; - dstep = (((double)(*val)) * u2s[unit]) / u2s[2]; /* in days */ + dstep = (((double)(*val)) * u2s[step_units]) / u2s[2]; /* in days */ dend += dstep; err = grib_julian_to_datetime(dend, &year_of_end_of_interval, &month_of_end_of_interval, @@ -495,19 +495,19 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) 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))) + if (time_range * u2s[step_units] % u2s2[time_range_unit]) { + time_range_unit = step_units; + if ((err = grib_set_long_internal(h, self->time_range_unit, time_range_unit))) return err; - coded_time_range = time_range; + time_range_value = time_range; } else - coded_time_range = (time_range * u2s[unit]) / u2s2[coded_unit]; + time_range_value = (time_range * u2s[step_units]) / u2s2[time_range_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))) + if ((err = grib_set_long_internal(h, self->time_range_value, time_range_value))) return err; } @@ -527,12 +527,12 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) if ((ret = unpack_long(a, &step_value, &step_len)) != GRIB_SUCCESS) return ret; - long step_units_old; - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_old)) != GRIB_SUCCESS) + long step_units; + if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) return ret; - Step step(step_value, step_units_old); - step.set_unit(step_units_old); + Step step(step_value, step_units); + step.set_unit(step_units); step.hide_hour_unit(); if (is_future_output_enabled(h)) { @@ -548,12 +548,12 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { - //grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; + 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.optimize_unit(); - if ((ret = grib_set_long_internal(h, "stepUnits", end_step.unit().to_long())) != GRIB_SUCCESS) + if ((ret = grib_set_long_internal(h, self->step_units, end_step.unit().to_long())) != GRIB_SUCCESS) return ret; long end_step_value = end_step.value(); diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index a6291b646..6482823ac 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -27,8 +27,8 @@ IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = get_native_type;string_length IMPLEMENTS = init - MEMBERS = const char* startStep - MEMBERS = const char* endStep + MEMBERS = const char* start_step + MEMBERS = const char* end_step END_CLASS_DEF */ @@ -57,8 +57,8 @@ typedef struct grib_accessor_g2step_range grib_accessor att; /* Members defined in gen */ /* Members defined in g2step_range */ - const char* startStep; - const char* endStep; + const char* start_step; + const char* end_step; } grib_accessor_g2step_range; extern grib_accessor_class* grib_accessor_class_gen; @@ -122,8 +122,8 @@ static void init(grib_accessor* a, const long l, grib_arguments* c) int n = 0; - self->startStep = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->endStep = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->start_step = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->end_step = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); a->length = 0; } @@ -140,34 +140,34 @@ 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; + long end_start_value = 0; + long end_step_value = 0; + long step_units = 0; - if ((ret = grib_get_long_internal(h, self->startStep, &start_value)) != GRIB_SUCCESS) + if ((ret = grib_get_long_internal(h, self->start_step, &end_start_value)) != GRIB_SUCCESS) return ret; - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_value)) != GRIB_SUCCESS) + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; - Step start_step = Step(start_value, step_units_value); + Step start_step{end_start_value, step_units}; start_step.hide_hour_unit(); - if (self->endStep == NULL) { + if (self->end_step == NULL) { if (is_future_output_enabled(h)) { snprintf(buf, sizeof(buf), "%s", start_step.to_string().c_str()); } else { - snprintf(buf, sizeof(buf), "%ld", start_value); + snprintf(buf, sizeof(buf), "%ld", end_start_value); } } else { - if ((ret = grib_get_long_internal(h, self->endStep, &end_value)) != GRIB_SUCCESS) + if ((ret = grib_get_long_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) return ret; if (is_future_output_enabled(h)) { - Step end_step = Step(end_value, step_units_value); + Step end_step{end_step_value, step_units}; end_step.hide_hour_unit(); - if (start_value == end_value) { + if (end_start_value == end_step_value) { snprintf(buf, sizeof(buf), "%s", end_step.to_string().c_str()); } else { @@ -175,11 +175,11 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) } } else { - if (start_value == end_value) { - snprintf(buf, sizeof(buf), "%ld", end_value); + if (end_start_value == end_step_value) { + snprintf(buf, sizeof(buf), "%ld", end_step_value); } else { - snprintf(buf, sizeof(buf), "%ld-%ld", start_value, end_value); + snprintf(buf, sizeof(buf), "%ld-%ld", end_start_value, end_step_value); } } @@ -216,11 +216,11 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) return ret; } - if ((ret = grib_set_long_internal(h, self->startStep, step_0.value()))) + if ((ret = grib_set_long_internal(h, self->start_step, step_0.value()))) return ret; - if ((self->endStep != NULL) && (steps.size() > 1)) { - if ((ret = grib_set_long_internal(h, self->endStep, step_1.value()))) + if ((self->end_step != NULL) && (steps.size() > 1)) { + if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) return ret; } return GRIB_SUCCESS; @@ -254,24 +254,24 @@ static int unpack_long(grib_accessor* a, long* 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; + long end_start_value = 0; + long end_step_value = 0; + long step_units = 0; - if ((ret = grib_get_long_internal(h, self->startStep, &start_value)) != GRIB_SUCCESS) + if ((ret = grib_get_long_internal(h, self->start_step, &end_start_value)) != GRIB_SUCCESS) return ret; - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_value)) != GRIB_SUCCESS) + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; - Step start_step = Step(start_value, step_units_value); + Step start_step{end_start_value, step_units}; start_step.hide_hour_unit(); - if (self->endStep == NULL) { + if (self->end_step == NULL) { *val = start_step.value(); } else { - if ((ret = grib_get_long_internal(h, self->endStep, &end_value)) != GRIB_SUCCESS) + if ((ret = grib_get_long_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) return ret; - Step end_step = Step(end_value, step_units_value); + Step end_step{end_step_value, step_units}; *val = end_step.value(); } diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 79d9cf054..39ce04304 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -25,10 +25,10 @@ IMPLEMENTS = pack_string;unpack_string;dump IMPLEMENTS = get_native_type;string_length IMPLEMENTS = init - MEMBERS = const char* forecastTime - MEMBERS = const char* indicatorOfUnitOfTimeRange - MEMBERS = const char* lengthOfTimeRange - MEMBERS = const char* indicatorOfUnitForTimeRange + MEMBERS = const char* forecast_time_value + MEMBERS = const char* forecast_time_unit + MEMBERS = const char* time_range_value + MEMBERS = const char* time_range_unit END_CLASS_DEF */ @@ -57,10 +57,10 @@ typedef struct grib_accessor_optimal_step_units grib_accessor att; /* Members defined in gen */ /* Members defined in optimal_step_units */ - const char* forecastTime; - const char* indicatorOfUnitOfTimeRange; - const char* lengthOfTimeRange; - const char* indicatorOfUnitForTimeRange; + const char* forecast_time_value; + const char* forecast_time_unit; + const char* time_range_value; + const char* time_range_unit; } grib_accessor_optimal_step_units; extern grib_accessor_class* grib_accessor_class_gen; @@ -124,10 +124,10 @@ static void init(grib_accessor* a, const long l, grib_arguments* c) int n = 0; - self->forecastTime = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->indicatorOfUnitOfTimeRange = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->lengthOfTimeRange = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->indicatorOfUnitForTimeRange= grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->forecast_time_value = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->forecast_time_unit = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->time_range_value = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->time_range_unit= grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); a->length = 0; } @@ -167,18 +167,18 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - auto forecast_time_opt = get_step(h, self->forecastTime, self->indicatorOfUnitOfTimeRange); - auto lenght_of_time_range_opt = get_step(h, self->lengthOfTimeRange, self->indicatorOfUnitForTimeRange); + auto forecast_time_opt = get_step(h, self->forecast_time_value, self->forecast_time_unit); + auto time_range_opt = get_step(h, self->time_range_value, self->time_range_unit); - if (!(forecast_time_opt && lenght_of_time_range_opt)) { + if (!(forecast_time_opt && time_range_opt)) { *val = UnitType{Unit::HOUR}.to_long(); return GRIB_SUCCESS; } Step forecast_time = forecast_time_opt.value_or(Step{}); - Step length_of_time_range = lenght_of_time_range_opt.value_or(Step{}); + Step time_range = time_range_opt.value_or(Step{}); - auto [step_a, step_b] = find_common_units(forecast_time.optimize_unit(), (forecast_time + length_of_time_range).optimize_unit()); + auto [step_a, step_b] = find_common_units(forecast_time.optimize_unit(), (forecast_time + time_range).optimize_unit()); *val = step_a.unit().to_long(); return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 598015bd1..a609f55d6 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -21,11 +21,11 @@ IMPLEMENTS = unpack_long;pack_long IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = init;dump - MEMBERS = const char* codedStep - MEMBERS = const char* codedUnits - MEMBERS = const char* stepUnits - MEMBERS = const char* indicatorOfUnitForTimeRange - MEMBERS = const char* lengthOfTimeRange + MEMBERS = const char* forecast_time_value + MEMBERS = const char* forecast_time_unit + MEMBERS = const char* step_units + MEMBERS = const char* time_range_unit + MEMBERS = const char* time_range_value END_CLASS_DEF @@ -54,11 +54,11 @@ typedef struct grib_accessor_step_in_units /* Members defined in gen */ /* Members defined in long */ /* Members defined in step_in_units */ - const char* codedStep; - const char* codedUnits; - const char* stepUnits; - const char* indicatorOfUnitForTimeRange; - const char* lengthOfTimeRange; + const char* forecast_time_value; + const char* forecast_time_unit; + const char* step_units; + const char* time_range_unit; + const char* time_range_value; } grib_accessor_step_in_units; extern grib_accessor_class* grib_accessor_class_long; @@ -121,11 +121,11 @@ static void init(grib_accessor* a, const long l, grib_arguments* c) grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; int n = 0; - self->codedStep = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->codedUnits = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->stepUnits = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->indicatorOfUnitForTimeRange = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->lengthOfTimeRange = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->forecast_time_value = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->forecast_time_unit = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->step_units = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->time_range_unit = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->time_range_value = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); } static void dump(grib_accessor* a, grib_dumper* dumper) @@ -151,7 +151,7 @@ static const int u2s2[] = { 1 /* (13) seconds */ }; -/* Note: 'stepUnits' has a different table with extra entries e.g. 15 and 30 mins */ +/* Note: 'step_units' has a different table with extra entries e.g. 15 and 30 mins */ static const int u2s[] = { 60, /* (0) minutes */ 3600, /* (1) hour */ @@ -176,44 +176,44 @@ 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; + long forecast_time_value, forecast_time_unit, step_units; grib_handle* h = grib_handle_of_accessor(a); int factor = 0; long u2sf, u2sf_step_unit; - if ((err = grib_get_long_internal(h, self->codedUnits, &codedUnits))) + if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) return err; - if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits))) + if ((err = grib_get_long_internal(h, self->step_units, &step_units))) return err; - if ((err = grib_get_long_internal(h, self->codedStep, &codedStep))) + if ((err = grib_get_long_internal(h, self->forecast_time_value, &forecast_time_value))) return err; - if (stepUnits != codedUnits) { - *val = codedStep * u2s2[codedUnits]; + if (step_units != forecast_time_unit) { + *val = forecast_time_value * u2s2[forecast_time_unit]; if (*val < 0) { factor = 60; - if (u2s2[codedUnits] % factor) + if (u2s2[forecast_time_unit] % factor) return GRIB_DECODING_ERROR; - if (u2s[stepUnits] % factor) + if (u2s[step_units] % factor) return GRIB_DECODING_ERROR; - u2sf = u2s2[codedUnits] / factor; - *val = codedStep * u2sf; - u2sf_step_unit = u2s[stepUnits] / factor; + u2sf = u2s2[forecast_time_unit] / factor; + *val = forecast_time_value * u2sf; + u2sf_step_unit = u2s[step_units] / factor; } else { - u2sf_step_unit = u2s[stepUnits]; + u2sf_step_unit = u2s[step_units]; } if (*val % u2sf_step_unit != 0) { - err = grib_set_long_internal(h, self->stepUnits, codedUnits); - *val = codedStep; + err = grib_set_long_internal(h, self->step_units, forecast_time_unit); + *val = forecast_time_value; return err; } *val = *val / u2sf_step_unit; } else - *val = codedStep; + *val = forecast_time_value; return GRIB_SUCCESS; } @@ -224,63 +224,63 @@ 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 err = 0; - long codedStep, codedUnits, stepUnits; + long forecast_time_value, forecast_time_unit, step_units; long oldStep = 0; - long indicatorOfUnitForTimeRange, lengthOfTimeRange; + long time_range_unit, time_range_value; - if ((err = grib_get_long_internal(h, self->codedUnits, &codedUnits))) + if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) return err; - if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits))) + if ((err = grib_get_long_internal(h, self->step_units, &step_units))) return err; unpack_long(a, &oldStep, len); - if (stepUnits != codedUnits) { - codedStep = *val * u2s[stepUnits]; - if (codedStep % u2s2[codedUnits] != 0) { - codedUnits = stepUnits; - err = grib_set_long_internal(h, self->codedUnits, codedUnits); + if (step_units != forecast_time_unit) { + forecast_time_value = *val * u2s[step_units]; + if (forecast_time_value % u2s2[forecast_time_unit] != 0) { + forecast_time_unit = step_units; + err = grib_set_long_internal(h, self->forecast_time_unit, forecast_time_unit); if (err != GRIB_SUCCESS) return err; - codedStep = *val; + forecast_time_value = *val; } else { - codedStep = codedStep / u2s2[codedUnits]; + forecast_time_value = forecast_time_value / u2s2[forecast_time_unit]; } } else { - codedStep = *val; + forecast_time_value = *val; } - if (self->indicatorOfUnitForTimeRange) { + if (self->time_range_unit) { if ((err = grib_get_long_internal(h, - self->indicatorOfUnitForTimeRange, &indicatorOfUnitForTimeRange))) + self->time_range_unit, &time_range_unit))) return err; if ((err = grib_get_long_internal(h, - self->lengthOfTimeRange, &lengthOfTimeRange))) + self->time_range_value, &time_range_value))) return err; - if (codedUnits == indicatorOfUnitForTimeRange) - lengthOfTimeRange -= codedStep - oldStep; + if (forecast_time_unit == time_range_unit) + time_range_value -= forecast_time_value - oldStep; else - lengthOfTimeRange -= codedStep * u2s2[codedUnits] / u2s2[indicatorOfUnitForTimeRange]; - lengthOfTimeRange = lengthOfTimeRange > 0 ? lengthOfTimeRange : 0; + time_range_value -= forecast_time_value * u2s2[forecast_time_unit] / u2s2[time_range_unit]; + time_range_value = time_range_value > 0 ? time_range_value : 0; - //lengthOfTimeRange = lengthOfTimeRange * u2s2[indicatorOfUnitForTimeRange] / u2s2[stepUnits]; - codedUnits = stepUnits; - err = grib_set_long_internal(grib_handle_of_accessor(a), self->lengthOfTimeRange, lengthOfTimeRange); + //time_range_value = time_range_value * u2s2[time_range_unit] / u2s2[step_units]; + forecast_time_unit = step_units; + err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range_value); if (err != GRIB_SUCCESS) return err; - //err = grib_set_long_internal(grib_handle_of_accessor(a), self->indicatorOfUnitForTimeRange, codedUnits); + //err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, forecast_time_unit); //if (err != GRIB_SUCCESS) // return err; - //err = grib_set_long_internal(grib_handle_of_accessor(a), self->codedUnits, codedUnits); + //err = grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_unit, forecast_time_unit); //if (err != GRIB_SUCCESS) // return err; } - return grib_set_long_internal(grib_handle_of_accessor(a), self->codedStep, codedStep); + return grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_value, forecast_time_value); } @@ -293,13 +293,13 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) Step step = step_from_string(val); long step_units; - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) return ret; long value; - if (self->indicatorOfUnitForTimeRange != NULL) { + if (self->time_range_unit != NULL) { long end_step_value; if ((ret = grib_get_long_internal(h, "endStep", &end_step_value)) != GRIB_SUCCESS) @@ -307,13 +307,13 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) Step end_step{end_step_value, UnitType{step_units}}; auto [step_a, step_b] = find_common_units(step, end_step); - if ((ret = grib_set_long_internal(h, "stepUnits", step_b.unit().to_long())) != GRIB_SUCCESS) + if ((ret = grib_set_long_internal(h, self->step_units, step_b.unit().to_long())) != GRIB_SUCCESS) return ret; if ((ret = grib_set_long_internal(h, "endStep", step_b.value())) != GRIB_SUCCESS) return ret; - //if ((ret = set_step(h, self->lengthOfTimeRange, self->indicatorOfUnitForTimeRange, step_b)) != GRIB_SUCCESS) + //if ((ret = set_step(h, self->time_range_value, self->time_range_unit, step_b)) != GRIB_SUCCESS) //return ret; value = step.value(step_a.unit()); @@ -342,7 +342,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; long step_units; - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) return ret; Step step{value, step_units}; From 0244a922c58216987a89807f0826043870bb1400 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 30 Aug 2023 11:59:04 +0000 Subject: [PATCH 026/125] ECC-1620: Encode low level keys with the same unit --- src/grib_accessor_class_g2end_step.cc | 58 +++++++++++---- src/grib_accessor_class_step_in_units.cc | 89 +++++++++++++----------- tests/grib_ecc-1620.sh | 16 ++--- 3 files changed, 101 insertions(+), 62 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 74987a952..cb3479708 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -429,7 +429,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) long minute_of_end_of_interval = 0; long second_of_end_of_interval = 0; - long time_range_value, time_range, typeOfTimeIncrement; + long time_range_value, time_range_v, typeOfTimeIncrement; double dend, dstep; @@ -461,9 +461,9 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement))) return err; - time_range = *val - start_step_value; + time_range_v = *val - start_step_value; - if (time_range < 0) { + if (time_range_v < 0) { grib_context_log(h->context, GRIB_LOG_ERROR, "endStep < startStep (%ld < %ld)", *val, start_step_value); return GRIB_WRONG_STEP; @@ -495,21 +495,55 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) if ((err = grib_set_long_internal(h, self->second_of_end_of_interval, second_of_end_of_interval))) return err; - if (time_range * u2s[step_units] % u2s2[time_range_unit]) { + if (time_range_v * u2s[step_units] % u2s2[time_range_unit]) { time_range_unit = step_units; if ((err = grib_set_long_internal(h, self->time_range_unit, time_range_unit))) return err; - time_range_value = time_range; + time_range_value = time_range_v; } else - time_range_value = (time_range * u2s[step_units]) / u2s2[time_range_unit]; + time_range_value = (time_range_v * u2s[step_units]) / u2s2[time_range_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->time_range_value, time_range_value))) - return err; - } + + time_range_value = time_range_value * u2s[time_range_unit] / u2s2[step_units]; + time_range_unit = step_units; + if ((err = grib_set_long_internal(h, self->time_range_value, time_range_value))) + return err; + if ((err = grib_set_long_internal(h, self->time_range_unit, time_range_unit))) + return err; + + + + const char* forecast_time_value_key = "forecastTime"; + const char* forecast_time_unit_key = "indicatorOfUnitOfTimeRange"; + long forecast_time_value; + long forecast_time_unit; + if ((err = grib_get_long_internal(h, forecast_time_value_key, &forecast_time_value)) != GRIB_SUCCESS) + return err; + if ((err = grib_get_long_internal(h, forecast_time_unit_key, &forecast_time_unit)) != GRIB_SUCCESS) + return err; + + + //auto [forecast_time, time_range] = find_common_units(Step{forecast_time_value, forecast_time_unit}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); + auto [forecast_time, time_range] = find_common_units(Step{start_step_value, step_units}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); + + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range.value())) != GRIB_SUCCESS) + return err; + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, time_range.unit().to_long())) != GRIB_SUCCESS) + return err; + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_value_key, forecast_time.value())) != GRIB_SUCCESS) + return err; + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_unit_key, forecast_time.unit().to_long())) != GRIB_SUCCESS) + return err; + + + + //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->time_range_value, time_range_value))) + // return err; + //} return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index a609f55d6..a4555b999 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -225,7 +225,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int err = 0; long forecast_time_value, forecast_time_unit, step_units; - long oldStep = 0; + long forecast_time_value_old = 0; long time_range_unit, time_range_value; if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) @@ -235,13 +235,13 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) - unpack_long(a, &oldStep, len); + unpack_long(a, &forecast_time_value_old, len); if (step_units != forecast_time_unit) { forecast_time_value = *val * u2s[step_units]; if (forecast_time_value % u2s2[forecast_time_unit] != 0) { forecast_time_unit = step_units; - err = grib_set_long_internal(h, self->forecast_time_unit, forecast_time_unit); + err = grib_set_long_internal(h, self->forecast_time_unit, forecast_time_unit); if (err != GRIB_SUCCESS) return err; forecast_time_value = *val; @@ -255,29 +255,28 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) } if (self->time_range_unit) { - if ((err = grib_get_long_internal(h, - self->time_range_unit, &time_range_unit))) + if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) return err; - if ((err = grib_get_long_internal(h, - self->time_range_value, &time_range_value))) + if ((err = grib_get_long_internal(h, self->time_range_value, &time_range_value))) return err; if (forecast_time_unit == time_range_unit) - time_range_value -= forecast_time_value - oldStep; + time_range_value -= forecast_time_value - forecast_time_value_old; else time_range_value -= forecast_time_value * u2s2[forecast_time_unit] / u2s2[time_range_unit]; time_range_value = time_range_value > 0 ? time_range_value : 0; - //time_range_value = time_range_value * u2s2[time_range_unit] / u2s2[step_units]; - forecast_time_unit = step_units; - err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range_value); - if (err != GRIB_SUCCESS) + time_range_value = time_range_value * u2s2[time_range_unit] / u2s2[forecast_time_unit]; + time_range_unit = forecast_time_unit; + auto [forecast_time, time_range] = find_common_units(Step{forecast_time_value, forecast_time_unit}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); + + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range.value())) != GRIB_SUCCESS) + return err; + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, time_range.unit().to_long())) != GRIB_SUCCESS) + return err; + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_value, forecast_time.value())) != GRIB_SUCCESS) + return err; + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_unit, forecast_time.unit().to_long())) != GRIB_SUCCESS) return err; - //err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, forecast_time_unit); - //if (err != GRIB_SUCCESS) - // return err; - //err = grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_unit, forecast_time_unit); - //if (err != GRIB_SUCCESS) - // return err; } return grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_value, forecast_time_value); @@ -297,34 +296,40 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) return ret; + long value = step.value(); - long value; - if (self->time_range_unit != NULL) { - - long end_step_value; - if ((ret = grib_get_long_internal(h, "endStep", &end_step_value)) != GRIB_SUCCESS) - return ret; - Step end_step{end_step_value, UnitType{step_units}}; - - auto [step_a, step_b] = find_common_units(step, end_step); - if ((ret = grib_set_long_internal(h, self->step_units, step_b.unit().to_long())) != GRIB_SUCCESS) - return ret; - - if ((ret = grib_set_long_internal(h, "endStep", step_b.value())) != GRIB_SUCCESS) - return ret; - - //if ((ret = set_step(h, self->time_range_value, self->time_range_unit, step_b)) != GRIB_SUCCESS) - //return ret; - - value = step.value(step_a.unit()); - } - else { - value = step.value(UnitType{step_units}); - } - + if ((ret = grib_set_long_internal(h, "stepUnits", step.unit().to_long())) != GRIB_SUCCESS) + return ret; if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS) return ret; + //long value; + //if (self->time_range_unit != NULL) { + + // long end_step_value; + // if ((ret = grib_get_long_internal(h, "endStep", &end_step_value)) != GRIB_SUCCESS) + // return ret; + // Step end_step{end_step_value, UnitType{step_units}}; + + // auto [step_a, step_b] = find_common_units(step, end_step); + // if ((ret = grib_set_long_internal(h, self->step_units, step_b.unit().to_long())) != GRIB_SUCCESS) + // return ret; + + // if ((ret = grib_set_long_internal(h, "endStep", step_b.value())) != GRIB_SUCCESS) + // return ret; + + // //if ((ret = set_step(h, self->time_range_value, self->time_range_unit, step_b)) != GRIB_SUCCESS) + // //return ret; + + // value = step.value(step_a.unit()); + //} + //else { + // value = step.value(UnitType{step_units}); + //} + + //if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS) + // return ret; + //if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS) //return ret; diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 3dc3583b7..948e060b2 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -64,29 +64,29 @@ 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" +grib_check_key_equals $temp2 "-y -p $low_level_keys" "1440 m 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" +grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 24000 h" # 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" +grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 24 h" #${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" +grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 24 h" #${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" +grib_check_key_equals $temp2 "-y -p $low_level_keys" "4 m 1440 m" #${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" +grib_check_key_equals $temp2 "-y -p $low_level_keys" "2 h 24 h" @@ -109,11 +109,11 @@ 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 $low_level_keys" "60 m 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 $low_level_keys" "1488 h 1440 h" grib_check_key_equals $temp2 "-y -p stepRange:s" "1488-2928" #${tools_dir}/grib_set -s $fn $temp From 371be8028319fbcf030a1901ed0c3a073053af1f Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 31 Aug 2023 13:30:10 +0000 Subject: [PATCH 027/125] ECC-1620: Don't modify endStep, when changing startStep --- src/grib_accessor_class_g2end_step.cc | 4 +- src/grib_accessor_class_g2step_range.cc | 45 ++++++- src/grib_accessor_class_step_in_units.cc | 157 +++++++++++++++++++---- tests/grib_ecc-1620.sh | 53 +++++--- 4 files changed, 213 insertions(+), 46 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index cb3479708..f7b84e238 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -39,8 +39,8 @@ MEMBERS = const char* minute_of_end_of_interval MEMBERS = const char* second_of_end_of_interval - MEMBERS = const char* time_range_unit // indicatorOfUnitForTimeRange - MEMBERS = const char* time_range_value // lengthOfTimeRange + MEMBERS = const char* time_range_unit + MEMBERS = const char* time_range_value MEMBERS = const char* typeOfTimeIncrement MEMBERS = const char* numberOfTimeRange diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 6482823ac..a2de8bed1 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -198,7 +198,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) } -static int pack_string(grib_accessor* a, const char* val, size_t* len) +static int pack_string_old(grib_accessor* a, const char* val, size_t* len) { grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; grib_handle* h = grib_handle_of_accessor(a); @@ -226,6 +226,49 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) return GRIB_SUCCESS; } + +static int pack_string_new(grib_accessor* a, const char* 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; + + std::vector steps = parse_range(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) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); + if ((ret = grib_set_long_internal(h, "stepUnits", step_0.unit().to_long()))) + return ret; + } + + //if ((ret = grib_set_long_internal(h, self->start_step, step_0.value()))) + // return ret; + if ((ret = set_step(h, "forecastTime" , "indicatorOfUnitOfTimeRange", step_0)) != GRIB_SUCCESS) + return ret; + + if ((self->end_step != NULL) && (steps.size() > 1)) { + if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) + return ret; + } + return GRIB_SUCCESS; +} + +static int pack_string(grib_accessor* a, const char* val, size_t* len) +{ + grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; + grib_handle* h = grib_handle_of_accessor(a); + if (is_future_output_enabled(h)) { + return pack_string_new(a, val, len); + } + else { + return pack_string_old(a, val, len); + } +} + static int value_count(grib_accessor* a, long* count) { *count = 1; diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index a4555b999..f2733d63b 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -219,13 +219,12 @@ 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) -{ +int pack_long_old_(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 err = 0; long forecast_time_value, forecast_time_unit, step_units; - long forecast_time_value_old = 0; + long oldStep = 0; long time_range_unit, time_range_value; if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) @@ -233,15 +232,13 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) if ((err = grib_get_long_internal(h, self->step_units, &step_units))) return err; - - - unpack_long(a, &forecast_time_value_old, len); + unpack_long(a, &oldStep, len); if (step_units != forecast_time_unit) { forecast_time_value = *val * u2s[step_units]; if (forecast_time_value % u2s2[forecast_time_unit] != 0) { forecast_time_unit = step_units; - err = grib_set_long_internal(h, self->forecast_time_unit, forecast_time_unit); + err = grib_set_long_internal(h, self->forecast_time_unit, forecast_time_unit); if (err != GRIB_SUCCESS) return err; forecast_time_value = *val; @@ -255,33 +252,149 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) } if (self->time_range_unit) { - if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) + if ((err = grib_get_long_internal(h, + self->time_range_unit, &time_range_unit))) return err; - if ((err = grib_get_long_internal(h, self->time_range_value, &time_range_value))) + if ((err = grib_get_long_internal(h, + self->time_range_value, &time_range_value))) return err; if (forecast_time_unit == time_range_unit) - time_range_value -= forecast_time_value - forecast_time_value_old; + time_range_value -= forecast_time_value - oldStep; else time_range_value -= forecast_time_value * u2s2[forecast_time_unit] / u2s2[time_range_unit]; time_range_value = time_range_value > 0 ? time_range_value : 0; - - time_range_value = time_range_value * u2s2[time_range_unit] / u2s2[forecast_time_unit]; - time_range_unit = forecast_time_unit; - auto [forecast_time, time_range] = find_common_units(Step{forecast_time_value, forecast_time_unit}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); - - if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range.value())) != GRIB_SUCCESS) - return err; - if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, time_range.unit().to_long())) != GRIB_SUCCESS) - return err; - if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_value, forecast_time.value())) != GRIB_SUCCESS) - return err; - if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_unit, forecast_time.unit().to_long())) != GRIB_SUCCESS) + err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range_value); + if (err != GRIB_SUCCESS) return err; } return grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_value, forecast_time_value); } +int pack_long_new_(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 err = 0; + //long forecast_time_value; + long forecast_time_unit; + long step_units; + long start_step_value_old= 0; + long time_range_unit; + long time_range_value; + + if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit)) != GRIB_SUCCESS) + return err; + if ((err = unpack_long(a, &start_step_value_old, len)) != GRIB_SUCCESS) + return err; + if ((err = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) + return err; + Step start_step_old(start_step_value_old, step_units); + Step forecast_time(*val, step_units); + Step time_range_new{}; + + auto time_range_opt = get_step(h, self->time_range_value, self->time_range_unit); + if (time_range_opt) { + auto time_range = time_range_opt.value(); + time_range = time_range - (forecast_time - start_step_old); + auto [sa, sb] = find_common_units(forecast_time.optimize_unit(), time_range.optimize_unit()); + if ((err = set_step(h, self->forecast_time_value, self->forecast_time_unit, sa)) != GRIB_SUCCESS) + return err; + if ((err = set_step(h, self->time_range_value, self->time_range_unit, sb)) != GRIB_SUCCESS) + return err; + return GRIB_SUCCESS; + } + + forecast_time.optimize_unit(); + if ((err = set_step(h, self->forecast_time_value, self->forecast_time_unit, forecast_time)) != GRIB_SUCCESS) + return err; + + // if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) + // return err; + // if ((err = grib_get_long_internal(h, self->time_range_value, &time_range_value))) + // return err; + // if (forecast_time_unit == time_range_unit) + // time_range_value -= forecast_time_value - forecast_time_value_old; + // else + // time_range_value -= forecast_time_value * u2s2[forecast_time_unit] / u2s2[time_range_unit]; + // time_range_value = time_range_value > 0 ? time_range_value : 0; + + 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 forecast_time_value, forecast_time_unit, step_units; + //long forecast_time_value_old = 0; + //long time_range_unit, time_range_value; + + //if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) + // return err; + //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) + // return err; + + //unpack_long(a, &forecast_time_value_old, len); + + //if (step_units != forecast_time_unit) { + // forecast_time_value = *val * u2s[step_units]; + // if (forecast_time_value % u2s2[forecast_time_unit] != 0) { + // forecast_time_unit = step_units; + // err = grib_set_long_internal(h, self->forecast_time_unit, forecast_time_unit); + // if (err != GRIB_SUCCESS) + // return err; + // forecast_time_value = *val; + // } + // else { + // forecast_time_value = forecast_time_value / u2s2[forecast_time_unit]; + // } + //} + //else { + // forecast_time_value = *val; + //} + + //if (self->time_range_unit) { + // if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) + // return err; + // if ((err = grib_get_long_internal(h, self->time_range_value, &time_range_value))) + // return err; + // if (forecast_time_unit == time_range_unit) + // time_range_value -= forecast_time_value - forecast_time_value_old; + // else + // time_range_value -= forecast_time_value * u2s2[forecast_time_unit] / u2s2[time_range_unit]; + // time_range_value = time_range_value > 0 ? time_range_value : 0; + + // time_range_value = time_range_value * u2s2[time_range_unit] / u2s2[forecast_time_unit]; + // time_range_unit = forecast_time_unit; + // auto [forecast_time, time_range] = find_common_units(Step{forecast_time_value, forecast_time_unit}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); + + // if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range.value())) != GRIB_SUCCESS) + // return err; + // if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, time_range.unit().to_long())) != GRIB_SUCCESS) + // return err; + // if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_value, forecast_time.value())) != GRIB_SUCCESS) + // return err; + // if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_unit, forecast_time.unit().to_long())) != GRIB_SUCCESS) + // return err; + //} + + //return grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_value, forecast_time_value); + +} + +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; + if (is_future_output_enabled(h)) { + ret = pack_long_new_(a, val, len); + } + else { + ret = pack_long_old_(a, val, len); + } + + return ret; +} + static int pack_string(grib_accessor* a, const char* val, size_t* len) { diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 948e060b2..29bc07479 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -46,6 +46,27 @@ temp2=temp_2.$label + +#fn="${data_dir}/reduced_gaussian_sub_area.grib2" +#low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" +##high_level_keys="startStep:s,endStep:s" +#high_level_keys="startStep:i,endStep:i" +#${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=1,indicatorOfUnitForTimeRange=D $fn $temp +#grib_check_key_equals $temp "-y -p $low_level_keys" "24 h 1 D" +#grib_check_key_equals $temp "-y -p $high_level_keys" "24 48" +#${tools_dir}/grib_set -y -s startStep:i=24 $temp $temp2 +#grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 0 h" +#grib_check_key_equals $temp2 "-y -p $high_level_keys" "24 24" + +#${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=24,indicatorOfUnitForTimeRange=h $fn $temp +#grib_check_key_equals $temp "-y -p $low_level_keys" "24 h 24 h" +#grib_check_key_equals $temp "-y -p $high_level_keys" "24 48" +#${tools_dir}/grib_set -y -s startStep:i=24 $temp $temp2 +#grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 24 h" +#grib_check_key_equals $temp2 "-y -p $high_level_keys" "24 48" +#exit + + #### CHECK: grib_set - endStep + stepUnits fn="${data_dir}/reduced_gaussian_sub_area.grib2" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" @@ -53,12 +74,17 @@ ${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h,lengthOfTi 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 +${tools_dir}/grib_set -y -s endStep:d=30 $temp $temp2 # TODO(EB) remove in the future behavior +#${tools_dir}/grib_set -y -s endStep:i=30 $temp $temp2 # TODO(EB) keep for backwards compatibility +#${tools_dir}/grib_set -y -s endStep:s=30 $temp $temp2 +#${tools_dir}/grib_set -y -s endStep:s=30h $temp $temp2 +#${tools_dir}/grib_set -y -s endStep=30h $temp $temp2 # TODO(EB) add to tests 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=30 $temp $temp2 ${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 @@ -72,21 +98,21 @@ grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 24000 h" # 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 24 h" +grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 43 h" #${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 24 h" +grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 43 h" #${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 1440 m" +grib_check_key_equals $temp2 "-y -p $low_level_keys" "4 m 2876 m" #${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 24 h" +grib_check_key_equals $temp2 "-y -p $low_level_keys" "2 h 46 h" @@ -116,21 +142,6 @@ ${tools_dir}/grib_set -y -s stepRange:s=62D-122D $temp $temp2 grib_check_key_equals $temp2 "-y -p $low_level_keys" "1488 h 1440 h" grib_check_key_equals $temp2 "-y -p stepRange:s" "1488-2928" -#${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" @@ -147,7 +158,7 @@ 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_s -F"%.2f" -s stepUnits=h" "0.983333" # TODO(EB): check behaviour // See tools for default output format 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 From cf154eb62eb2122e4cccd17a0101a9b3fb2ce01f Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 31 Aug 2023 15:56:49 +0000 Subject: [PATCH 028/125] ECC-1620: Don't use variable-length arrays --- src/step_utilities.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/step_utilities.cc b/src/step_utilities.cc index 808010bcb..11a1c015e 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -37,7 +37,7 @@ int set_step(grib_handle* h, const std::string& value_key, const std::string& un bool is_future_output_enabled(grib_handle* h) { size_t step_output_format_size = 128; - char step_output_format[step_output_format_size]; + char step_output_format[128]; int ret = 0; if ((ret = grib_get_string_internal(h, "stepOutputFormat", step_output_format, &step_output_format_size)) != GRIB_SUCCESS) return ret; From c51203a7570e81fc07066dd1968d9e37a4345a95 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Thu, 31 Aug 2023 16:56:50 +0100 Subject: [PATCH 029/125] ISO C++17 does not allow 'register' storage class specifier [-Wregister] --- src/grib_accessor_classes_hash.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/grib_accessor_classes_hash.cc b/src/grib_accessor_classes_hash.cc index 8f0f5075f..32a13c8d1 100644 --- a/src/grib_accessor_classes_hash.cc +++ b/src/grib_accessor_classes_hash.cc @@ -52,7 +52,7 @@ struct accessor_class_hash { char *name; grib_accessor_class **cclass;}; #endif #endif static unsigned int -grib_accessor_classes_get_id (register const char *str, register size_t len) +grib_accessor_classes_get_id (const char *str, size_t len) { static const unsigned short asso_values[] = { @@ -83,7 +83,7 @@ grib_accessor_classes_get_id (register const char *str, register size_t len) 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680 }; - register unsigned int hval = len; + unsigned int hval = len; switch (hval) { @@ -690,15 +690,15 @@ static const struct accessor_class_hash classes[] = }; const struct accessor_class_hash * -grib_accessor_classes_hash (register const char *str, register size_t len) +grib_accessor_classes_hash ( const char *str, size_t len) { if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { - register unsigned int key = grib_accessor_classes_get_id (str, len); + unsigned int key = grib_accessor_classes_get_id (str, len); if (key <= MAX_HASH_VALUE) { - register const char *s = classes[key].name; + const char *s = classes[key].name; if (*str == *s && !strcmp (str + 1, s + 1)) return &classes[key]; From 546b9851cbc4dfd23bae95a02739b6b57a6f4e7d Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Thu, 31 Aug 2023 17:02:12 +0100 Subject: [PATCH 030/125] Compiler warnings --- src/grib_accessor_class_g2step_range.cc | 11 ++++------- src/grib_accessor_class_optimal_step_units.cc | 11 +++++------ src/grib_accessor_class_step_in_units.cc | 5 ++--- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index a2de8bed1..09f2778a2 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -128,10 +128,10 @@ static void init(grib_accessor* a, const long l, grib_arguments* c) a->length = 0; } -static void dump(grib_accessor* a, grib_dumper* dumper) -{ - grib_dump_string(dumper, a, NULL); -} +//static void dump(grib_accessor* a, grib_dumper* dumper) +//{ + //grib_dump_string(dumper, a, NULL); +//} static int unpack_string(grib_accessor* a, char* val, size_t* len) { @@ -259,7 +259,6 @@ static int pack_string_new(grib_accessor* a, const char* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { - grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; grib_handle* h = grib_handle_of_accessor(a); if (is_future_output_enabled(h)) { return pack_string_new(a, val, len); @@ -294,9 +293,7 @@ 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); - char buf[100]; int ret = 0; - size_t size = 0; long end_start_value = 0; long end_step_value = 0; long step_units = 0; diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 39ce04304..d2f0c370e 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -137,11 +137,11 @@ static void dump(grib_accessor* a, grib_dumper* dumper) } -static int value_count(grib_accessor* a, long* count) -{ - *count = 1; - return 0; -} +//static int value_count(grib_accessor* a, long* count) +//{ + //*count = 1; + //return 0; +//} static size_t string_length(grib_accessor* a) { @@ -165,7 +165,6 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) } grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; grib_handle* h = grib_handle_of_accessor(a); - int ret = 0; auto forecast_time_opt = get_step(h, self->forecast_time_value, self->forecast_time_unit); auto time_range_opt = get_step(h, self->time_range_value, self->time_range_unit); diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index f2733d63b..de5b3cec6 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -279,8 +279,8 @@ int pack_long_new_(grib_accessor* a, const long* val, size_t* len) { long forecast_time_unit; long step_units; long start_step_value_old= 0; - long time_range_unit; - long time_range_value; + //long time_range_unit; + //long time_range_value; if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit)) != GRIB_SUCCESS) return err; @@ -382,7 +382,6 @@ int pack_long_new_(grib_accessor* a, const 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; if (is_future_output_enabled(h)) { From 610f3845842704bd3b28865ec84eeade5f458eb7 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 31 Aug 2023 16:10:57 +0000 Subject: [PATCH 031/125] ECC-1620: Clean-up --- src/grib_accessor_class_step_in_units.cc | 101 ----------------------- 1 file changed, 101 deletions(-) diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index de5b3cec6..a4baca1be 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -308,76 +308,7 @@ int pack_long_new_(grib_accessor* a, const long* val, size_t* len) { if ((err = set_step(h, self->forecast_time_value, self->forecast_time_unit, forecast_time)) != GRIB_SUCCESS) return err; - // if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) - // return err; - // if ((err = grib_get_long_internal(h, self->time_range_value, &time_range_value))) - // return err; - // if (forecast_time_unit == time_range_unit) - // time_range_value -= forecast_time_value - forecast_time_value_old; - // else - // time_range_value -= forecast_time_value * u2s2[forecast_time_unit] / u2s2[time_range_unit]; - // time_range_value = time_range_value > 0 ? time_range_value : 0; - 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 forecast_time_value, forecast_time_unit, step_units; - //long forecast_time_value_old = 0; - //long time_range_unit, time_range_value; - - //if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) - // return err; - //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - // return err; - - //unpack_long(a, &forecast_time_value_old, len); - - //if (step_units != forecast_time_unit) { - // forecast_time_value = *val * u2s[step_units]; - // if (forecast_time_value % u2s2[forecast_time_unit] != 0) { - // forecast_time_unit = step_units; - // err = grib_set_long_internal(h, self->forecast_time_unit, forecast_time_unit); - // if (err != GRIB_SUCCESS) - // return err; - // forecast_time_value = *val; - // } - // else { - // forecast_time_value = forecast_time_value / u2s2[forecast_time_unit]; - // } - //} - //else { - // forecast_time_value = *val; - //} - - //if (self->time_range_unit) { - // if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) - // return err; - // if ((err = grib_get_long_internal(h, self->time_range_value, &time_range_value))) - // return err; - // if (forecast_time_unit == time_range_unit) - // time_range_value -= forecast_time_value - forecast_time_value_old; - // else - // time_range_value -= forecast_time_value * u2s2[forecast_time_unit] / u2s2[time_range_unit]; - // time_range_value = time_range_value > 0 ? time_range_value : 0; - - // time_range_value = time_range_value * u2s2[time_range_unit] / u2s2[forecast_time_unit]; - // time_range_unit = forecast_time_unit; - // auto [forecast_time, time_range] = find_common_units(Step{forecast_time_value, forecast_time_unit}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); - - // if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range.value())) != GRIB_SUCCESS) - // return err; - // if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, time_range.unit().to_long())) != GRIB_SUCCESS) - // return err; - // if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_value, forecast_time.value())) != GRIB_SUCCESS) - // return err; - // if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_unit, forecast_time.unit().to_long())) != GRIB_SUCCESS) - // return err; - //} - - //return grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_value, forecast_time_value); - } static int pack_long(grib_accessor* a, const long* val, size_t* len) @@ -394,7 +325,6 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return ret; } - 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; @@ -407,7 +337,6 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) return ret; - long value = step.value(); if ((ret = grib_set_long_internal(h, "stepUnits", step.unit().to_long())) != GRIB_SUCCESS) @@ -415,36 +344,6 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS) return ret; - //long value; - //if (self->time_range_unit != NULL) { - - // long end_step_value; - // if ((ret = grib_get_long_internal(h, "endStep", &end_step_value)) != GRIB_SUCCESS) - // return ret; - // Step end_step{end_step_value, UnitType{step_units}}; - - // auto [step_a, step_b] = find_common_units(step, end_step); - // if ((ret = grib_set_long_internal(h, self->step_units, step_b.unit().to_long())) != GRIB_SUCCESS) - // return ret; - - // if ((ret = grib_set_long_internal(h, "endStep", step_b.value())) != GRIB_SUCCESS) - // return ret; - - // //if ((ret = set_step(h, self->time_range_value, self->time_range_unit, step_b)) != GRIB_SUCCESS) - // //return ret; - - // value = step.value(step_a.unit()); - //} - //else { - // value = step.value(UnitType{step_units}); - //} - - //if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS) - // return ret; - - //if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS) - //return ret; - return GRIB_SUCCESS; } From b2c8b6876decb1f99b3f56e987cc733d22c3a524 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 4 Sep 2023 10:15:50 +0000 Subject: [PATCH 032/125] ECC-1620: Optimize performance --- src/grib_accessor_classes_hash.cc | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/grib_accessor_classes_hash.cc b/src/grib_accessor_classes_hash.cc index 32a13c8d1..8456336e5 100644 --- a/src/grib_accessor_classes_hash.cc +++ b/src/grib_accessor_classes_hash.cc @@ -689,20 +689,20 @@ static const struct accessor_class_hash classes[] = {"g1forecastmonth", &grib_accessor_class_g1forecastmonth} }; -const struct accessor_class_hash * -grib_accessor_classes_hash ( const char *str, size_t len) + +static const struct accessor_class_hash *grib_accessor_classes_hash(const char *str, size_t len) { - if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + unsigned int key = grib_accessor_classes_get_id (str, len); + +#ifdef DEBUG { - unsigned int key = grib_accessor_classes_get_id (str, len); - - if (key <= MAX_HASH_VALUE) - { - const char *s = classes[key].name; - - if (*str == *s && !strcmp (str + 1, s + 1)) - return &classes[key]; - } + 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 ); } - return 0; +#endif + + return &classes[key]; } From a08c2cec4a9f8a5fc04088b9c4140cc7077cf1a7 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 4 Sep 2023 13:01:19 +0000 Subject: [PATCH 033/125] ECC-1620: Recompute optimal step units for each message --- .../grib2/template.4.forecast_time.def | 5 +- src/grib_accessor_class_g2end_step.cc | 30 +- src/grib_accessor_class_g2step_range.cc | 52 +-- src/grib_accessor_class_optimal_step_units.cc | 38 +- src/grib_accessor_class_step_in_units.cc | 45 ++- src/step_utilities.cc | 15 + src/step_utilities.h | 1 + tests/grib_ecc-1620.sh | 361 ++++++++---------- 8 files changed, 257 insertions(+), 290 deletions(-) diff --git a/definitions/grib2/template.4.forecast_time.def b/definitions/grib2/template.4.forecast_time.def index 600be0616..4a9c6f410 100644 --- a/definitions/grib2/template.4.forecast_time.def +++ b/definitions/grib2/template.4.forecast_time.def @@ -14,8 +14,9 @@ codetable[1] indicatorOfUnitOfTimeRange ('4.4.table',masterDir,localDir) : dump #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; -transient useOptimalStepUnits = 0; -meta stepUnits optimal_step_units(forecastTime,indicatorOfUnitOfTimeRange,lengthOfTimeRange,indicatorOfUnitForTimeRange) : dump; +codetable[1] stepUnits 'stepUnits.table' = 255 : transient,dump,no_copy; +#transient useOptimalStepUnits = 0; +meta optimalStepUnits 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/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index f7b84e238..8e73f4d2b 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -281,8 +281,9 @@ static int unpack_one_time_range_long_(grib_accessor* a, long* val, size_t* len) if ((err = grib_get_long_internal(h, self->start_step_value, &start_step_value))) return err; - if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - return err; + //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) + //return err; + step_units = get_step_units(h); if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) return err; if ((err = grib_get_long_internal(h, self->time_range_value, &time_range_value))) @@ -328,8 +329,9 @@ static int unpack_multiple_time_ranges_long_(grib_accessor* a, long* val, size_t if ((err = grib_get_long_internal(h, self->start_step_value, &start_step_value))) return err; - if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - return err; + //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) + //return err; + step_units = get_step_units(h); if ((err = grib_get_long_internal(h, self->numberOfTimeRange, &numberOfTimeRange))) return err; if (numberOfTimeRange > MAX_NUM_TIME_RANGES) { @@ -441,8 +443,9 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) return err; - if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - return err; + //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) + //return err; + step_units = get_step_units(h); if ((err = grib_get_long_internal(h, self->year, &year))) return err; if ((err = grib_get_long_internal(h, self->month, &month))) @@ -562,19 +565,20 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; long step_units; - if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) - return ret; + //if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) + //return ret; + step_units = get_step_units(h); Step step(step_value, step_units); step.set_unit(step_units); step.hide_hour_unit(); - if (is_future_output_enabled(h)) { + //if (is_future_output_enabled(h)) { snprintf(val, *len, "%s", step.to_string().c_str()); - } - else { - snprintf(val, *len, "%ld", step.value()); - } + //} + //else { + // snprintf(val, *len, "%ld", step.value()); + //} return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 09f2778a2..d4312cfcd 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -146,25 +146,26 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) if ((ret = grib_get_long_internal(h, self->start_step, &end_start_value)) != GRIB_SUCCESS) return ret; - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) - return ret; + //if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + // return ret; + step_units = get_step_units(h); Step start_step{end_start_value, step_units}; start_step.hide_hour_unit(); if (self->end_step == NULL) { - if (is_future_output_enabled(h)) { + //if (is_future_output_enabled(h)) { snprintf(buf, sizeof(buf), "%s", start_step.to_string().c_str()); - } - else { - snprintf(buf, sizeof(buf), "%ld", end_start_value); - } + //} + //else { + // snprintf(buf, sizeof(buf), "%ld", end_start_value); + //} } else { if ((ret = grib_get_long_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) return ret; - if (is_future_output_enabled(h)) { + //if (is_future_output_enabled(h)) { Step end_step{end_step_value, step_units}; end_step.hide_hour_unit(); if (end_start_value == end_step_value) { @@ -173,15 +174,15 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) else { snprintf(buf, sizeof(buf), "%s-%s", start_step.to_string().c_str(), end_step.to_string().c_str()); } - } - else { - if (end_start_value == end_step_value) { - snprintf(buf, sizeof(buf), "%ld", end_step_value); - } - else { - snprintf(buf, sizeof(buf), "%ld-%ld", end_start_value, end_step_value); - } - } + //} + //else { + // if (end_start_value == end_step_value) { + // snprintf(buf, sizeof(buf), "%ld", end_step_value); + // } + // else { + // snprintf(buf, sizeof(buf), "%ld-%ld", end_start_value, end_step_value); + // } + //} } @@ -259,13 +260,13 @@ static int pack_string_new(grib_accessor* a, const char* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { - grib_handle* h = grib_handle_of_accessor(a); - if (is_future_output_enabled(h)) { + //grib_handle* h = grib_handle_of_accessor(a); + //if (is_future_output_enabled(h)) { return pack_string_new(a, val, len); - } - else { - return pack_string_old(a, val, len); - } + //} + //else { + // return pack_string_old(a, val, len); + //} } static int value_count(grib_accessor* a, long* count) @@ -300,8 +301,9 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) if ((ret = grib_get_long_internal(h, self->start_step, &end_start_value)) != GRIB_SUCCESS) return ret; - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) - return ret; + //if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + // return ret; + step_units = get_step_units(h); Step start_step{end_start_value, step_units}; start_step.hide_hour_unit(); diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index d2f0c370e..3ed171d0f 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -21,9 +21,9 @@ START_CLASS_DEF CLASS = accessor SUPER = grib_accessor_class_gen - IMPLEMENTS = pack_long;unpack_long;dump - IMPLEMENTS = pack_string;unpack_string;dump - IMPLEMENTS = get_native_type;string_length + IMPLEMENTS = unpack_long;dump + IMPLEMENTS = unpack_string;dump + IMPLEMENTS = string_length IMPLEMENTS = init MEMBERS = const char* forecast_time_value MEMBERS = const char* forecast_time_unit @@ -84,13 +84,13 @@ static grib_accessor_class _grib_accessor_class_optimal_step_units = { 0, /* get sub_section */ 0, /* pack_missing */ 0, /* is_missing */ - &pack_long, /* pack_long */ + 0, /* pack_long */ &unpack_long, /* unpack_long */ 0, /* pack_double */ 0, /* pack_float */ 0, /* unpack_double */ 0, /* unpack_float */ - &pack_string, /* pack_string */ + 0, /* pack_string */ &unpack_string, /* unpack_string */ 0, /* pack_string_array */ 0, /* unpack_string_array */ @@ -150,19 +150,19 @@ static size_t string_length(grib_accessor* a) static long staticStepUnits = UnitType{Unit::MISSING}.to_long(); -static int pack_long(grib_accessor* a, const long* val, size_t* len) -{ - staticStepUnits = *val; +//static int pack_long(grib_accessor* a, const long* val, size_t* len) +//{ +// staticStepUnits = *val; - return GRIB_SUCCESS; -} +// return GRIB_SUCCESS; +//} static int unpack_long(grib_accessor* a, long* val, size_t* len) { - if (staticStepUnits != 255) { - *val = staticStepUnits; - return GRIB_SUCCESS; - } + //if (staticStepUnits != 255) { + // *val = staticStepUnits; + // return GRIB_SUCCESS; + //} grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; grib_handle* h = grib_handle_of_accessor(a); @@ -183,11 +183,11 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) } -static int pack_string(grib_accessor* a, const char* val, size_t* len) -{ - staticStepUnits = UnitType{val}.to_long(); - return GRIB_SUCCESS; -} +//static int pack_string(grib_accessor* a, const char* val, size_t* len) +//{ +// staticStepUnits = UnitType{val}.to_long(); +// return GRIB_SUCCESS; +//} static int unpack_string(grib_accessor* a, char* val, size_t* len) { diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index a4baca1be..e70043201 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -184,8 +184,9 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) return err; - if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - return err; + //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) + // return err; + step_units = get_step_units(h); if ((err = grib_get_long_internal(h, self->forecast_time_value, &forecast_time_value))) return err; @@ -229,8 +230,9 @@ int pack_long_old_(grib_accessor* a, const long* val, size_t* len) { if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) return err; - if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - return err; + //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) + // return err; + step_units = get_step_units(h); unpack_long(a, &oldStep, len); @@ -286,8 +288,9 @@ int pack_long_new_(grib_accessor* a, const long* val, size_t* len) { return err; if ((err = unpack_long(a, &start_step_value_old, len)) != GRIB_SUCCESS) return err; - if ((err = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) - return err; + //if ((err = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) + //return err; + step_units = get_step_units(h); Step start_step_old(start_step_value_old, step_units); Step forecast_time(*val, step_units); Step time_range_new{}; @@ -315,12 +318,12 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); int ret; - if (is_future_output_enabled(h)) { + //if (is_future_output_enabled(h)) { ret = pack_long_new_(a, val, len); - } - else { - ret = pack_long_old_(a, val, len); - } + //} + //else { + // ret = pack_long_old_(a, val, len); + //} return ret; } @@ -334,8 +337,9 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) Step step = step_from_string(val); long step_units; - if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) - return ret; + //if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) + // return ret; + step_units = get_step_units(h); long value = step.value(); @@ -358,19 +362,20 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; long step_units; - if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) - return ret; + //if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) + // return ret; + step_units = get_step_units(h); Step step{value, step_units}; step.hide_hour_unit(); //snprintf(val, *len, "%ld", value); - if (is_future_output_enabled(h)) { + //if (is_future_output_enabled(h)) { snprintf(val, *len, "%s", step.to_string().c_str()); - } - else { - snprintf(val, *len, "%ld", step.value()); - } + //} + //else { + // snprintf(val, *len, "%ld", step.value()); + //} return GRIB_SUCCESS; } diff --git a/src/step_utilities.cc b/src/step_utilities.cc index 11a1c015e..f2bedef10 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -43,3 +43,18 @@ bool is_future_output_enabled(grib_handle* h) return ret; return strcmp(step_output_format, "future") == 0; } + + +long get_step_units(grib_handle* h) +{ + int ret = 0; + long step_units = 0; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + throw std::runtime_error("Failed to get stepUnits"); + + if (step_units == 255) { + if((ret = grib_get_long_internal(h, "optimalStepUnits", &step_units)) != GRIB_SUCCESS) + throw std::runtime_error("Failed to get optimalStepUnits"); + } + return step_units; +} diff --git a/src/step_utilities.h b/src/step_utilities.h index 65176a76c..9926f5938 100644 --- a/src/step_utilities.h +++ b/src/step_utilities.h @@ -7,6 +7,7 @@ std::optional get_step(grib_handle* h, const std::string& value_key, const std::string& unit_key); bool is_future_output_enabled(grib_handle* h); int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step); +long get_step_units(grib_handle* h); //template //int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 29bc07479..916f2b8b5 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -52,18 +52,18 @@ temp2=temp_2.$label ##high_level_keys="startStep:s,endStep:s" #high_level_keys="startStep:i,endStep:i" #${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=1,indicatorOfUnitForTimeRange=D $fn $temp -#grib_check_key_equals $temp "-y -p $low_level_keys" "24 h 1 D" -#grib_check_key_equals $temp "-y -p $high_level_keys" "24 48" -#${tools_dir}/grib_set -y -s startStep:i=24 $temp $temp2 -#grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 0 h" -#grib_check_key_equals $temp2 "-y -p $high_level_keys" "24 24" +#grib_check_key_equals $temp "-p $low_level_keys" "24 h 1 D" +#grib_check_key_equals $temp "-p $high_level_keys" "24 48" +#${tools_dir}/grib_set -s startStep:i=24 $temp $temp2 +#grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 0 h" +#grib_check_key_equals $temp2 "-p $high_level_keys" "24 24" #${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=24,indicatorOfUnitForTimeRange=h $fn $temp -#grib_check_key_equals $temp "-y -p $low_level_keys" "24 h 24 h" -#grib_check_key_equals $temp "-y -p $high_level_keys" "24 48" -#${tools_dir}/grib_set -y -s startStep:i=24 $temp $temp2 -#grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 24 h" -#grib_check_key_equals $temp2 "-y -p $high_level_keys" "24 48" +#grib_check_key_equals $temp "-p $low_level_keys" "24 h 24 h" +#grib_check_key_equals $temp "-p $high_level_keys" "24 48" +#${tools_dir}/grib_set -s startStep:i=24 $temp $temp2 +#grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 24 h" +#grib_check_key_equals $temp2 "-p $high_level_keys" "24 48" #exit @@ -74,73 +74,73 @@ ${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h,lengthOfTi 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 # TODO(EB) remove in the future behavior -#${tools_dir}/grib_set -y -s endStep:i=30 $temp $temp2 # TODO(EB) keep for backwards compatibility -#${tools_dir}/grib_set -y -s endStep:s=30 $temp $temp2 -#${tools_dir}/grib_set -y -s endStep:s=30h $temp $temp2 -#${tools_dir}/grib_set -y -s endStep=30h $temp $temp2 # TODO(EB) add to tests -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" +${tools_dir}/grib_set -s endStep:d=30 $temp $temp2 # TODO(EB) remove in the future behavior +#${tools_dir}/grib_set -s endStep:i=30 $temp $temp2 # TODO(EB) keep for backwards compatibility +#${tools_dir}/grib_set -s endStep:s=30 $temp $temp2 +#${tools_dir}/grib_set -s endStep:s=30h $temp $temp2 +#${tools_dir}/grib_set -s endStep=30h $temp $temp2 # TODO(EB) add to tests +grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 6 h" +#${tools_dir}/grib_set -s endStep:d=24.5 $temp $temp2 +#grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 30 m" # Use stepUnits -${tools_dir}/grib_set -y -s endStep:s=30 $temp $temp2 -${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" "1440 m 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 24000 h" +${tools_dir}/grib_set -s endStep:s=30 $temp $temp2 +${tools_dir}/grib_set -s endStep:s=30h $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 6 h" +#${tools_dir}/grib_set -s endStep:s=24.5h $temp $temp2 +#grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 30 m" +${tools_dir}/grib_set -s endStep:s=88200s $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "1440 m 30 m" +#${tools_dir}/grib_set -s endStep:s=1446.65m $temp $temp2 +#grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 399 s" +${tools_dir}/grib_set -s endStep:s=24024 $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 24000 h" # 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 43 h" -#${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" +${tools_dir}/grib_set -s startStep:d=5 $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "5 h 43 h" +#${tools_dir}/grib_set -s startStep:d=4.5 $temp $temp2 +#grib_check_key_equals $temp2 "-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 43 h" -#${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 2876 m" -#${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 46 h" +${tools_dir}/grib_set -s startStep:s=5h $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "5 h 43 h" +#${tools_dir}/grib_set -s startStep:s=4.5h $temp $temp2 +#grib_check_key_equals $temp2 "-p $low_level_keys" "270 m 1 D" +${tools_dir}/grib_set -s startStep:s=240s $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "4 m 2876 m" +#${tools_dir}/grib_set -s startStep:s=0.65m $temp $temp2 +#grib_check_key_equals $temp2 "-p $low_level_keys" "39 s 1 D" +${tools_dir}/grib_set -s startStep:s=2 $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "2 h 46 h" -${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 -s stepRange:s=5h-30h $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "5 h 25 h" +grib_check_key_equals $temp2 "-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 -s stepRange:s=5-30 $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "5 h 25 h" +grib_check_key_equals $temp2 "-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 -s stepRange:s=60m-120m $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "1 h 1 h" +grib_check_key_equals $temp2 "-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 -s stepRange:s=60s-120s $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 1 m" +grib_check_key_equals $temp2 "-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" "60 m 61 m" -grib_check_key_equals $temp2 "-y -p stepRange:s" "60m-121m" +${tools_dir}/grib_set -s stepRange:s=60m-121m $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "60 m 61 m" +grib_check_key_equals $temp2 "-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 1440 h" -grib_check_key_equals $temp2 "-y -p stepRange:s" "1488-2928" +${tools_dir}/grib_set -s stepRange:s=62D-122D $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "1488 h 1440 h" +grib_check_key_equals $temp2 "-p stepRange:s" "1488-2928" @@ -153,27 +153,27 @@ 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_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 -F"%.2f" -s stepUnits=h" "0.983333" # TODO(EB): check behaviour // See tools for default output format -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 +grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "3540" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "59" +#grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0" # TODO(EB): check behaviour (should be 0.983333) +grib_check_key_equals $temp "-p $keys_s -s stepUnits=s" "3540s" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "59m" +#grib_check_key_equals $temp "-p $keys_s -F"%.2f" -s stepUnits=h" "0.983333" # TODO(EB): check behaviour // See tools for default output format +grib_check_key_equals $temp "-p $keys_i -s stepUnits=s" "3540" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "59" +#grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0" # TODO(EB): check behaviour +grib_check_key_equals $temp "-p $keys_d -s stepUnits=s" "3540" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "59" +#grib_check_key_equals $temp "-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" -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 "-p $keys_i -s stepUnits=s" "0" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "0" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=s" "0" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "0" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0" @@ -187,83 +187,61 @@ 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" "0" -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 "-p $keys__" "0" +grib_check_key_equals $temp "-p $keys_s" "0" +grib_check_key_equals $temp "-p $keys_i" "0" +grib_check_key_equals $temp "-p $keys_d" "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" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "0" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "0" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=s" "0s" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "0m" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=h" "0" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=s" "0" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "0" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=s" "0" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "0" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0" ${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "59 m" -grib_check_key_equals $temp "-p $keys__" "59" -grib_check_key_equals $temp "-y -p $keys__" "59" -grib_check_key_equals $temp "-p $keys_s" "59" -grib_check_key_equals $temp "-y -p $keys_s" "59m" -grib_check_key_equals $temp "-p $keys_i" "59" -grib_check_key_equals $temp "-y -p $keys_i" "59" -grib_check_key_equals $temp "-p $keys_d" "59" -grib_check_key_equals $temp "-y -p $keys_d" "59" +grib_check_key_equals $temp "-p $keys__" "59" +#grib_check_key_equals $temp "-p $keys_s" "59" +grib_check_key_equals $temp "-p $keys_s" "59m" +grib_check_key_equals $temp "-p $keys_i" "59" +grib_check_key_equals $temp "-p $keys_d" "59" ${tools_dir}/grib_set -s forecastTime=60,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m" -grib_check_key_equals $temp "-p $keys__" "1" -grib_check_key_equals $temp "-y -p $keys__" "1" -grib_check_key_equals $temp "-p $keys_s" "1" -grib_check_key_equals $temp "-y -p $keys_s" "1" -grib_check_key_equals $temp "-p $keys_i" "1" -grib_check_key_equals $temp "-y -p $keys_i" "1" -grib_check_key_equals $temp "-p $keys_d" "1" -grib_check_key_equals $temp "-y -p $keys_d" "1" +grib_check_key_equals $temp "-p $keys__" "1" +grib_check_key_equals $temp "-p $keys_s" "1" +grib_check_key_equals $temp "-p $keys_i" "1" +grib_check_key_equals $temp "-p $keys_d" "1" ${tools_dir}/grib_set -s forecastTime=61,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "61 m" -grib_check_key_equals $temp "-p $keys__" "61" -grib_check_key_equals $temp "-y -p $keys__" "61" -grib_check_key_equals $temp "-p $keys_s" "61" -grib_check_key_equals $temp "-y -p $keys_s" "61m" -grib_check_key_equals $temp "-p $keys_i" "61" -grib_check_key_equals $temp "-y -p $keys_i" "61" -grib_check_key_equals $temp "-p $keys_d" "61" -grib_check_key_equals $temp "-y -p $keys_d" "61" +grib_check_key_equals $temp "-p $keys__" "61" +#grib_check_key_equals $temp "-p $keys_s" "61" +grib_check_key_equals $temp "-p $keys_s" "61m" +grib_check_key_equals $temp "-p $keys_i" "61" +grib_check_key_equals $temp "-p $keys_d" "61" ${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "24 h" -grib_check_key_equals $temp "-p $keys__" "24" -grib_check_key_equals $temp "-y -p $keys__" "24" -grib_check_key_equals $temp "-p $keys_s" "24" -grib_check_key_equals $temp "-y -p $keys_s" "24" -grib_check_key_equals $temp "-p $keys_i" "24" -grib_check_key_equals $temp "-y -p $keys_i" "24" -grib_check_key_equals $temp "-p $keys_d" "24" -grib_check_key_equals $temp "-y -p $keys_d" "24" +grib_check_key_equals $temp "-p $keys__" "24" +grib_check_key_equals $temp "-p $keys_s" "24" +grib_check_key_equals $temp "-p $keys_i" "24" +grib_check_key_equals $temp "-p $keys_d" "24" ${tools_dir}/grib_set -s forecastTime=1440,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "1440 m" -grib_check_key_equals $temp "-p $keys__" "24" -grib_check_key_equals $temp "-y -p $keys__" "24" -grib_check_key_equals $temp "-p $keys_s" "24" -grib_check_key_equals $temp "-y -p $keys_s" "24" -grib_check_key_equals $temp "-p $keys_i" "24" -grib_check_key_equals $temp "-y -p $keys_i" "24" -grib_check_key_equals $temp "-p $keys_d" "24" -grib_check_key_equals $temp "-y -p $keys_d" "24" +grib_check_key_equals $temp "-p $keys__" "24" +grib_check_key_equals $temp "-p $keys_s" "24" +grib_check_key_equals $temp "-p $keys_i" "24" +grib_check_key_equals $temp "-p $keys_d" "24" @@ -276,100 +254,61 @@ keys_d="stepRange:d,startStep:d,endStep:d" ${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=2,indicatorOfUnitForTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "0 m 2 h" -grib_check_key_equals $temp "-p $keys__" "0-2 0 2" -grib_check_key_equals $temp "-y -p $keys__" "0-2 0 2" -grib_check_key_equals $temp "-p $keys_s" "0-2 0 2" -grib_check_key_equals $temp "-y -p $keys_s" "0-2 0 2" -grib_check_key_equals $temp "-p $keys_i" "2 0 2" -grib_check_key_equals $temp "-y -p $keys_i" "2 0 2" -grib_check_key_equals $temp "-p $keys_d" "2 0 2" -grib_check_key_equals $temp "-y -p $keys_d" "2 0 2" +grib_check_key_equals $temp "-p $keys__" "0-2 0 2" +grib_check_key_equals $temp "-p $keys_s" "0-2 0 2" +grib_check_key_equals $temp "-p $keys_i" "2 0 2" +grib_check_key_equals $temp "-p $keys_d" "2 0 2" ${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" -grib_check_key_equals $temp "-p $keys__" "24-48 24 48" -grib_check_key_equals $temp "-y -p $keys__" "24-48 24 48" -grib_check_key_equals $temp "-p $keys_s" "24-48 24 48" -grib_check_key_equals $temp "-y -p $keys_s" "24-48 24 48" -grib_check_key_equals $temp "-p $keys_i" "48 24 48" -grib_check_key_equals $temp "-y -p $keys_i" "48 24 48" -grib_check_key_equals $temp "-p $keys_d" "48 24 48" -grib_check_key_equals $temp "-y -p $keys_d" "48 24 48" +grib_check_key_equals $temp "-p $keys__" "24-48 24 48" +grib_check_key_equals $temp "-p $keys_s" "24-48 24 48" +grib_check_key_equals $temp "-p $keys_i" "48 24 48" +grib_check_key_equals $temp "-p $keys_d" "48 24 48" ${tools_dir}/grib_set -s forecastTime=25,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=1,indicatorOfUnitForTimeRange=D $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "25 h 1 D" grib_check_key_equals $temp "-p $keys__" "25-49 25 49" -grib_check_key_equals $temp "-y -p $keys__" "25-49 25 49" -grib_check_key_equals $temp "-p $keys_s" "25-49 25 49" -grib_check_key_equals $temp "-y -p $keys_s" "25-49 25 49" -grib_check_key_equals $temp "-p $keys_i" "49 25 49" -grib_check_key_equals $temp "-y -p $keys_i" "49 25 49" -grib_check_key_equals $temp "-p $keys_d" "49 25 49" -grib_check_key_equals $temp "-y -p $keys_d" "49 25 49" - - -#grib_check_key_equals $temp "-y -s stepUnits=h -p $keys__" "1.0166666666666666" -#grib_check_key_equals $temp "-y -s stepUnits=h -p $keys_s" "1.0166666666666666" -#grib_check_key_equals $temp "-y -s stepUnits=h -p $keys_i" "1" -#grib_check_key_equals $temp "-y -s stepUnits=h -p $keys_d" "1.0166666666666666" - - +grib_check_key_equals $temp "-p $keys__" "25-49 25 49" +grib_check_key_equals $temp "-p $keys_s" "25-49 25 49" +grib_check_key_equals $temp "-p $keys_i" "49 25 49" +grib_check_key_equals $temp "-p $keys_d" "49 25 49" ${tools_dir}/grib_set -s forecastTime=45,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=15,indicatorOfUnitForTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "45 m 15 m" -grib_check_key_equals $temp "-p $keys__" "45-60 45 60" -grib_check_key_equals $temp "-y -p $keys__" "45m-60m 45 60" -grib_check_key_equals $temp "-p $keys_s" "45-60 45 60" -grib_check_key_equals $temp "-y -p $keys_s" "45m-60m 45m 60m" -grib_check_key_equals $temp "-p $keys_i" "60 45 60" -grib_check_key_equals $temp "-y -p $keys_i" "60 45 60" -grib_check_key_equals $temp "-p $keys_d" "60 45 60" -grib_check_key_equals $temp "-y -p $keys_d" "60 45 60" - +grib_check_key_equals $temp "-p $keys__" "45m-60m 45 60" +#grib_check_key_equals $temp "-p $keys_s" "45-60 45 60" +grib_check_key_equals $temp "-p $keys_s" "45m-60m 45m 60m" +grib_check_key_equals $temp "-p $keys_i" "60 45 60" +grib_check_key_equals $temp "-p $keys_d" "60 45 60" ${tools_dir}/grib_set -s forecastTime=60,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=2,indicatorOfUnitForTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m 2 h" -grib_check_key_equals $temp "-p $keys__" "1-3 1 3" -grib_check_key_equals $temp "-y -p $keys__" "1-3 1 3" -grib_check_key_equals $temp "-p $keys_s" "1-3 1 3" -grib_check_key_equals $temp "-y -p $keys_s" "1-3 1 3" -grib_check_key_equals $temp "-p $keys_i" "3 1 3" -grib_check_key_equals $temp "-y -p $keys_i" "3 1 3" -grib_check_key_equals $temp "-p $keys_d" "3 1 3" -grib_check_key_equals $temp "-y -p $keys_d" "3 1 3" +grib_check_key_equals $temp "-p $keys__" "1-3 1 3" +grib_check_key_equals $temp "-p $keys_s" "1-3 1 3" +grib_check_key_equals $temp "-p $keys_i" "3 1 3" +grib_check_key_equals $temp "-p $keys_d" "3 1 3" ${tools_dir}/grib_set -s forecastTime=18,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=6,indicatorOfUnitForTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "18 h 6 h" -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" -grib_check_key_equals $temp "-y -p $keys_i" "24 18 24" -grib_check_key_equals $temp "-p $keys_d" "24 18 24" -grib_check_key_equals $temp "-y -p $keys_d" "24 18 24" +grib_check_key_equals $temp "-p $keys__" "18-24 18 24" +grib_check_key_equals $temp "-p $keys_s" "18-24 18 24" +grib_check_key_equals $temp "-p $keys_i" "24 18 24" +grib_check_key_equals $temp "-p $keys_d" "24 18 24" ${tools_dir}/grib_set -s forecastTime=1080,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=360,indicatorOfUnitForTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "1080 m 360 m" -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" -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. +grib_check_key_equals $temp "-p $keys__" "18-24 18 24" +grib_check_key_equals $temp "-p $keys_s" "18-24 18 24" +grib_check_key_equals $temp "-p $keys_i" "24 18 24" +grib_check_key_equals $temp "-p $keys_d" "24 18 24" ${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" -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" -grib_check_key_equals $temp "-y -p $keys_i" "24 18 24" -grib_check_key_equals $temp "-p $keys_d" "24 18 24" -grib_check_key_equals $temp "-y -p $keys_d" "24 18 24" +grib_check_key_equals $temp "-p $keys__" "18-24 18 24" +grib_check_key_equals $temp "-p $keys_s" "18-24 18 24" +grib_check_key_equals $temp "-p $keys_i" "24 18 24" +grib_check_key_equals $temp "-p $keys_d" "24 18 24" rm -f $temp From b11a82edbbdc645ce09e701581c7a2e1bbb15ef5 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 4 Sep 2023 18:41:16 +0000 Subject: [PATCH 034/125] ECC-1620: Remove -y option --- src/grib_api_internal.h | 1 + src/grib_context.cc | 6 +++++- src/step_utilities.cc | 7 +------ tools/grib_options.cc | 1 - 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/grib_api_internal.h b/src/grib_api_internal.h index 9f413495b..57cd11b98 100644 --- a/src/grib_api_internal.h +++ b/src/grib_api_internal.h @@ -1097,6 +1097,7 @@ struct grib_context grib_trie* lists; grib_trie* expanded_descriptors; int file_pool_max_opened_files; + int is_future_step_format; #if GRIB_PTHREADS pthread_mutex_t mutex; #elif GRIB_OMP_THREADS diff --git a/src/grib_context.cc b/src/grib_context.cc index 90b531f6f..b66dce790 100644 --- a/src/grib_context.cc +++ b/src/grib_context.cc @@ -366,7 +366,8 @@ static grib_context default_grib_context = { 0, /* classes */ 0, /* lists */ 0, /* expanded_descriptors */ - DEFAULT_FILE_POOL_MAX_OPENED_FILES /* file_pool_max_opened_files */ + DEFAULT_FILE_POOL_MAX_OPENED_FILES, /* file_pool_max_opened_files */ + 0 #if GRIB_PTHREADS , PTHREAD_MUTEX_INITIALIZER /* mutex */ @@ -399,6 +400,7 @@ grib_context* grib_context_get_default() const char* grib_data_quality_checks = NULL; const char* single_precision = NULL; const char* file_pool_max_opened_files = NULL; + const char* is_future_step_format = NULL; #ifdef ENABLE_FLOATING_POINT_EXCEPTIONS feenableexcept(FE_ALL_EXCEPT & ~FE_INEXACT); @@ -421,6 +423,7 @@ grib_context* grib_context_get_default() no_spd = codes_getenv("ECCODES_GRIB_NO_SPD"); keep_matrix = codes_getenv("ECCODES_GRIB_KEEP_MATRIX"); file_pool_max_opened_files = getenv("ECCODES_FILE_POOL_MAX_OPENED_FILES"); + is_future_step_format = getenv("ECCODES_GRIB_IS_FUTURE_STEP_FORMAT"); /* On UNIX, when we read from a file we get exactly what is in the file on disk. * But on Windows a file can be opened in binary or text mode. In binary mode the system behaves exactly as in UNIX. @@ -555,6 +558,7 @@ grib_context* grib_context_get_default() default_grib_context.grib_data_quality_checks = grib_data_quality_checks ? atoi(grib_data_quality_checks) : 0; default_grib_context.single_precision = single_precision ? atoi(single_precision) : 0; default_grib_context.file_pool_max_opened_files = file_pool_max_opened_files ? atoi(file_pool_max_opened_files) : DEFAULT_FILE_POOL_MAX_OPENED_FILES; + default_grib_context.is_future_step_format = is_future_step_format ? atoi(is_future_step_format) : 0; } GRIB_MUTEX_UNLOCK(&mutex_c); diff --git a/src/step_utilities.cc b/src/step_utilities.cc index f2bedef10..22b9929f7 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -36,12 +36,7 @@ int set_step(grib_handle* h, const std::string& value_key, const std::string& un bool is_future_output_enabled(grib_handle* h) { - size_t step_output_format_size = 128; - char step_output_format[128]; - int ret = 0; - if ((ret = grib_get_string_internal(h, "stepOutputFormat", step_output_format, &step_output_format_size)) != GRIB_SUCCESS) - return ret; - return strcmp(step_output_format, "future") == 0; + return h->context->is_future_step_format > 0; } diff --git a/tools/grib_options.cc b/tools/grib_options.cc index 3e874369f..0d77dc67d 100644 --- a/tools/grib_options.cc +++ b/tools/grib_options.cc @@ -39,7 +39,6 @@ static grib_options_help grib_options_help_list[] = { { "e:", "tolerance", "\n\t\tOnly values whose difference is more than tolerance are considered different.\n" }, { "f", 0, "Force. Force the execution not to fail on error.\n" }, { "F:", "format", "\n\t\tC style format for floating-point values.\n" }, - { "y", "future", "\n\t\tFuture output format.\n" }, { "g", 0, "Copy GTS header. \n" }, { "G", 0, "GRIBEX compatibility mode.\n" }, { "i:", "index", From 982f46d16a3f210790789817b73abf73738d2ecd Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 4 Sep 2023 19:06:17 +0000 Subject: [PATCH 035/125] ECC-1620: Test conversion from step range to low level keys --- tests/grib_ecc-1620.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 916f2b8b5..7be6a6df3 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -245,6 +245,13 @@ grib_check_key_equals $temp "-p $keys_d" "24" + +fn="${data_dir}/reduced_gaussian_sub_area.grib2" +low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" +${tools_dir}/grib_set -s stepRange=60m-2h $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "1 h 1 h" + + fn="${data_dir}/reduced_gaussian_sub_area.grib2" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" keys__="stepRange,startStep,endStep" From 45267d146dae919dda506ae331f226b4e2a39696 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 15 Sep 2023 07:10:29 +0000 Subject: [PATCH 036/125] ECC-1620: Fix handing multiple messages in a GRIB file --- .../grib2/template.4.forecast_time.def | 6 +- src/grib_accessor_class_g2end_step.cc | 110 +++++++++++------- src/grib_accessor_class_g2step_range.cc | 96 +++++++-------- src/grib_accessor_class_optimal_step_units.cc | 56 ++++----- src/grib_accessor_class_step_in_units.cc | 87 ++++++-------- src/step.cc | 2 - src/step_utilities.cc | 8 +- src/step_utilities.h | 23 ---- tests/grib_ecc-1620.sh | 110 +++++++++--------- 9 files changed, 240 insertions(+), 258 deletions(-) diff --git a/definitions/grib2/template.4.forecast_time.def b/definitions/grib2/template.4.forecast_time.def index 4a9c6f410..2c0372e36 100644 --- a/definitions/grib2/template.4.forecast_time.def +++ b/definitions/grib2/template.4.forecast_time.def @@ -14,9 +14,9 @@ codetable[1] indicatorOfUnitOfTimeRange ('4.4.table',masterDir,localDir) : dump #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; -codetable[1] stepUnits 'stepUnits.table' = 255 : transient,dump,no_copy; -#transient useOptimalStepUnits = 0; -meta optimalStepUnits optimal_step_units(forecastTime,indicatorOfUnitOfTimeRange,lengthOfTimeRange,indicatorOfUnitForTimeRange) : dump; +meta stepUnits optimal_step_units(forecastTime,indicatorOfUnitOfTimeRange,lengthOfTimeRange,indicatorOfUnitForTimeRange) : dump; +transient startStepUnit = 255; +transient endStepUnit = 255; # Forecast time in units defined by previous octet (GRIB-29: supports negative forecast time) signed[4] forecastTime : dump; diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 8e73f4d2b..fa275eafd 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -409,7 +409,7 @@ 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) +static int pack_long_(grib_accessor* a, const long end_step_value, const long end_step_unit) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; grib_handle* h = grib_handle_of_accessor(a); @@ -423,6 +423,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) long second; long start_step_value; + long start_step_unit; long step_units, time_range_unit; long year_of_end_of_interval; long month_of_end_of_interval; @@ -435,17 +436,16 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) double dend, dstep; + Step end_step{end_step_value, end_step_unit}; + /*point in time */ if (self->year == NULL) { - err = grib_set_long_internal(h, self->start_step_value, *val); + err = grib_set_long_internal(h, self->start_step_value, end_step.value()); return err; } if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) return err; - //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - //return err; - step_units = get_step_units(h); if ((err = grib_get_long_internal(h, self->year, &year))) return err; if ((err = grib_get_long_internal(h, self->month, &month))) @@ -461,14 +461,23 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) if ((err = grib_get_long_internal(h, self->start_step_value, &start_step_value))) return err; + if ((err = grib_get_long_internal(h, "startStepUnit", &start_step_unit))) + return err; + if (start_step_unit == 255) { + throw std::runtime_error("startStepUnit == 255"); + } + if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement))) return err; - time_range_v = *val - start_step_value; + Step start_step{start_step_value, start_step_unit}; - if (time_range_v < 0) { + //time_range_v = *val - start_step_value; + Step time_range = end_step - start_step; + + if (time_range.value() < 0) { grib_context_log(h->context, GRIB_LOG_ERROR, - "endStep < startStep (%ld < %ld)", *val, start_step_value); + "endStep < startStep (%s < %s)", end_step.to_string().c_str(), start_step.to_string().c_str()); return GRIB_WRONG_STEP; } @@ -476,7 +485,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) if (err != GRIB_SUCCESS) return err; - dstep = (((double)(*val)) * u2s[step_units]) / u2s[2]; /* in days */ + dstep = end_step.value(UnitType{Unit::DAY}); dend += dstep; err = grib_julian_to_datetime(dend, &year_of_end_of_interval, &month_of_end_of_interval, @@ -498,45 +507,46 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) if ((err = grib_set_long_internal(h, self->second_of_end_of_interval, second_of_end_of_interval))) return err; - if (time_range_v * u2s[step_units] % u2s2[time_range_unit]) { - time_range_unit = step_units; - if ((err = grib_set_long_internal(h, self->time_range_unit, time_range_unit))) - return err; - time_range_value = time_range_v; - } - else - time_range_value = (time_range_v * u2s[step_units]) / u2s2[time_range_unit]; + //if (time_range_v * u2s[step_units] % u2s2[time_range_unit]) { + // time_range_unit = step_units; + // if ((err = grib_set_long_internal(h, self->time_range_unit, time_range_unit))) + // return err; + // time_range_value = time_range_v; + //} + //else + // time_range_value = (time_range_v * u2s[step_units]) / u2s2[time_range_unit]; - time_range_value = time_range_value * u2s[time_range_unit] / u2s2[step_units]; - time_range_unit = step_units; - if ((err = grib_set_long_internal(h, self->time_range_value, time_range_value))) - return err; - if ((err = grib_set_long_internal(h, self->time_range_unit, time_range_unit))) - return err; + //time_range_value = time_range_value * u2s[time_range_unit] / u2s2[step_units]; + //time_range_unit = step_units; + //if ((err = grib_set_long_internal(h, self->time_range_value, time_range_value))) + // return err; + //if ((err = grib_set_long_internal(h, self->time_range_unit, time_range_unit))) + // return err; const char* forecast_time_value_key = "forecastTime"; const char* forecast_time_unit_key = "indicatorOfUnitOfTimeRange"; - long forecast_time_value; - long forecast_time_unit; - if ((err = grib_get_long_internal(h, forecast_time_value_key, &forecast_time_value)) != GRIB_SUCCESS) - return err; - if ((err = grib_get_long_internal(h, forecast_time_unit_key, &forecast_time_unit)) != GRIB_SUCCESS) - return err; + //long forecast_time_value; + //long forecast_time_unit; + //if ((err = grib_get_long_internal(h, forecast_time_value_key, &forecast_time_value)) != GRIB_SUCCESS) + // return err; + //if ((err = grib_get_long_internal(h, forecast_time_unit_key, &forecast_time_unit)) != GRIB_SUCCESS) + // return err; //auto [forecast_time, time_range] = find_common_units(Step{forecast_time_value, forecast_time_unit}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); - auto [forecast_time, time_range] = find_common_units(Step{start_step_value, step_units}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); + //auto [forecast_time, time_range] = find_common_units(Step{start_step_value, step_units}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); + auto [forecast_time_opt, time_range_opt] = find_common_units(start_step, time_range); - if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range.value())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range_opt.value())) != GRIB_SUCCESS) return err; - if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, time_range.unit().to_long())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, time_range_opt.unit().to_long())) != GRIB_SUCCESS) return err; - if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_value_key, forecast_time.value())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_value_key, forecast_time_opt.value())) != GRIB_SUCCESS) return err; - if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_unit_key, forecast_time.unit().to_long())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_unit_key, forecast_time_opt.unit().to_long())) != GRIB_SUCCESS) return err; @@ -552,6 +562,7 @@ static int pack_long(grib_accessor* a, const long* 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; @@ -573,16 +584,27 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) step.set_unit(step_units); step.hide_hour_unit(); - //if (is_future_output_enabled(h)) { - snprintf(val, *len, "%s", step.to_string().c_str()); - //} - //else { - // snprintf(val, *len, "%ld", step.value()); - //} + snprintf(val, *len, "%s", step.to_string().c_str()); return GRIB_SUCCESS; } +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; + + long end_step_unit; + if ((ret = grib_get_long_internal(h, "endStepUnit", &end_step_unit)) != GRIB_SUCCESS) + return ret; + + if (end_step_unit == 255) + end_step_unit = UnitType{Unit::HOUR}.to_long(); + + return pack_long_(a, *val, end_step_unit); +} + static int pack_string(grib_accessor* a, const char* val, size_t* len) { @@ -591,13 +613,11 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) int ret = 0; Step end_step = step_from_string(val); end_step.optimize_unit(); - if ((ret = grib_set_long_internal(h, self->step_units, end_step.unit().to_long())) != GRIB_SUCCESS) + + if ((ret = grib_set_long_internal(h, "endStepUnit", end_step.unit().to_long())) != GRIB_SUCCESS) return ret; - long end_step_value = end_step.value(); - size_t end_step_len = 0; - - if ((ret = pack_long(a, &end_step_value, &end_step_len)) != GRIB_SUCCESS) + if ((ret = pack_long_(a, end_step.value(), end_step.unit().to_long())) != GRIB_SUCCESS) return ret; return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index d4312cfcd..580452eca 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -140,25 +140,28 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) char buf[100]; int ret = 0; size_t size = 0; - long end_start_value = 0; + long start_step_value = 0; long end_step_value = 0; - long step_units = 0; + long step_units; - if ((ret = grib_get_long_internal(h, self->start_step, &end_start_value)) != GRIB_SUCCESS) + if ((ret = grib_get_long_internal(h, self->start_step, &start_step_value)) != GRIB_SUCCESS) return ret; - //if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) - // return ret; - step_units = get_step_units(h); + if ((ret= grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + return ret; + if (step_units == 255) { + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + return ret; + } - Step start_step{end_start_value, step_units}; + Step start_step{start_step_value, step_units}; start_step.hide_hour_unit(); if (self->end_step == NULL) { //if (is_future_output_enabled(h)) { snprintf(buf, sizeof(buf), "%s", start_step.to_string().c_str()); //} //else { - // snprintf(buf, sizeof(buf), "%ld", end_start_value); + // snprintf(buf, sizeof(buf), "%ld", start_step_value); //} } else { @@ -168,7 +171,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) //if (is_future_output_enabled(h)) { Step end_step{end_step_value, step_units}; end_step.hide_hour_unit(); - if (end_start_value == end_step_value) { + if (start_step_value == end_step_value) { snprintf(buf, sizeof(buf), "%s", end_step.to_string().c_str()); } else { @@ -176,11 +179,11 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) } //} //else { - // if (end_start_value == end_step_value) { + // if (start_step_value == end_step_value) { // snprintf(buf, sizeof(buf), "%ld", end_step_value); // } // else { - // snprintf(buf, sizeof(buf), "%ld-%ld", end_start_value, end_step_value); + // snprintf(buf, sizeof(buf), "%ld-%ld", start_step_value, end_step_value); // } //} @@ -199,33 +202,33 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) } -static int pack_string_old(grib_accessor* a, const char* 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; +//static int pack_string_old(grib_accessor* a, const char* 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; - std::vector steps = parse_range(val); - if (steps.size() == 0) - return GRIB_INVALID_ARGUMENT; +// std::vector steps = parse_range(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) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); - if ((ret = grib_set_long_internal(h, "stepUnits", step_0.unit().to_long()))) - return ret; - } +// Step step_0 = steps[0]; +// Step step_1; +// if (steps.size() > 1) { +// std::tie(step_0, step_1) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); +// if ((ret = grib_set_long_internal(h, "stepUnits", step_0.unit().to_long()))) +// return ret; +// } - if ((ret = grib_set_long_internal(h, self->start_step, step_0.value()))) - return ret; +// if ((ret = grib_set_long_internal(h, self->start_step, step_0.value()))) +// return ret; - if ((self->end_step != NULL) && (steps.size() > 1)) { - if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) - return ret; - } - return GRIB_SUCCESS; -} +// if ((self->end_step != NULL) && (steps.size() > 1)) { +// if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) +// return ret; +// } +// return GRIB_SUCCESS; +//} static int pack_string_new(grib_accessor* a, const char* val, size_t* len) @@ -242,16 +245,16 @@ static int pack_string_new(grib_accessor* a, const char* val, size_t* len) Step step_1; if (steps.size() > 1) { std::tie(step_0, step_1) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); - if ((ret = grib_set_long_internal(h, "stepUnits", step_0.unit().to_long()))) - return ret; } - //if ((ret = grib_set_long_internal(h, self->start_step, step_0.value()))) - // return ret; + if ((ret = grib_set_long_internal(h, "startStepUnit", step_0.unit().to_long()))) + return ret; if ((ret = set_step(h, "forecastTime" , "indicatorOfUnitOfTimeRange", step_0)) != GRIB_SUCCESS) return ret; if ((self->end_step != NULL) && (steps.size() > 1)) { + if ((ret = grib_set_long_internal(h, "endStepUnit", step_1.unit().to_long()))) + return ret; if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) return ret; } @@ -260,13 +263,7 @@ static int pack_string_new(grib_accessor* a, const char* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { - //grib_handle* h = grib_handle_of_accessor(a); - //if (is_future_output_enabled(h)) { - return pack_string_new(a, val, len); - //} - //else { - // return pack_string_old(a, val, len); - //} + return pack_string_new(a, val, len); } static int value_count(grib_accessor* a, long* count) @@ -301,9 +298,12 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) if ((ret = grib_get_long_internal(h, self->start_step, &end_start_value)) != GRIB_SUCCESS) return ret; - //if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) - // return ret; - step_units = get_step_units(h); + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + throw std::runtime_error("Failed to get stepUnits"); + if (step_units == 255) { + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + return ret; + } Step start_step{end_start_value, step_units}; start_step.hide_hour_unit(); diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 3ed171d0f..20ff3b1be 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -21,8 +21,8 @@ START_CLASS_DEF CLASS = accessor SUPER = grib_accessor_class_gen - IMPLEMENTS = unpack_long;dump - IMPLEMENTS = unpack_string;dump + IMPLEMENTS = pack_long,unpack_long;dump + IMPLEMENTS = unpack_string,unpack_string;dump IMPLEMENTS = string_length IMPLEMENTS = init MEMBERS = const char* forecast_time_value @@ -84,13 +84,13 @@ static grib_accessor_class _grib_accessor_class_optimal_step_units = { 0, /* get sub_section */ 0, /* pack_missing */ 0, /* is_missing */ - 0, /* pack_long */ + &pack_long, /* pack_long */ &unpack_long, /* unpack_long */ 0, /* pack_double */ 0, /* pack_float */ 0, /* unpack_double */ 0, /* unpack_float */ - 0, /* pack_string */ + &pack_string, /* pack_string */ &unpack_string, /* unpack_string */ 0, /* pack_string_array */ 0, /* unpack_string_array */ @@ -150,44 +150,48 @@ static size_t string_length(grib_accessor* a) static long staticStepUnits = UnitType{Unit::MISSING}.to_long(); -//static int pack_long(grib_accessor* a, const long* val, size_t* len) -//{ -// staticStepUnits = *val; +static int pack_long(grib_accessor* a, const long* val, size_t* len) +{ + staticStepUnits = *val; -// return GRIB_SUCCESS; -//} + return GRIB_SUCCESS; +} static int unpack_long(grib_accessor* a, long* val, size_t* len) { - //if (staticStepUnits != 255) { - // *val = staticStepUnits; - // return GRIB_SUCCESS; - //} + if (staticStepUnits != 255) { + *val = staticStepUnits; + return GRIB_SUCCESS; + } + grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; grib_handle* h = grib_handle_of_accessor(a); auto forecast_time_opt = get_step(h, self->forecast_time_value, self->forecast_time_unit); auto time_range_opt = get_step(h, self->time_range_value, self->time_range_unit); - if (!(forecast_time_opt && time_range_opt)) { + if (forecast_time_opt && time_range_opt) { + auto [step_a, step_b] = find_common_units(forecast_time_opt.value().optimize_unit(), (forecast_time_opt.value() + time_range_opt.value()).optimize_unit()); + *val = step_a.unit().to_long(); + } + else if (forecast_time_opt && !time_range_opt) { + *val = forecast_time_opt.value().optimize_unit().unit().to_long(); + } + else if (!forecast_time_opt && time_range_opt) { + *val = time_range_opt.value().optimize_unit().unit().to_long(); + } + else if (!forecast_time_opt && !time_range_opt) { *val = UnitType{Unit::HOUR}.to_long(); - return GRIB_SUCCESS; } - Step forecast_time = forecast_time_opt.value_or(Step{}); - Step time_range = time_range_opt.value_or(Step{}); - - auto [step_a, step_b] = find_common_units(forecast_time.optimize_unit(), (forecast_time + time_range).optimize_unit()); - *val = step_a.unit().to_long(); return GRIB_SUCCESS; } - -//static int pack_string(grib_accessor* a, const char* val, size_t* len) -//{ -// staticStepUnits = UnitType{val}.to_long(); -// return GRIB_SUCCESS; -//} +static int pack_string(grib_accessor* a, const char* val, size_t* len) +{ + staticStepUnits = UnitType{val}.to_long(); + return GRIB_SUCCESS; +} static int unpack_string(grib_accessor* a, char* val, size_t* len) { diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index e70043201..4e2d3c17b 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -181,40 +181,19 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) int factor = 0; long u2sf, u2sf_step_unit; - + if ((err= grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + return err; if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) return err; - //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - // return err; - step_units = get_step_units(h); if ((err = grib_get_long_internal(h, self->forecast_time_value, &forecast_time_value))) return err; - if (step_units != forecast_time_unit) { - *val = forecast_time_value * u2s2[forecast_time_unit]; - if (*val < 0) { - factor = 60; - if (u2s2[forecast_time_unit] % factor) - return GRIB_DECODING_ERROR; - if (u2s[step_units] % factor) - return GRIB_DECODING_ERROR; - u2sf = u2s2[forecast_time_unit] / factor; - *val = forecast_time_value * u2sf; - u2sf_step_unit = u2s[step_units] / factor; - } - else { - u2sf_step_unit = u2s[step_units]; - } + Step step{forecast_time_value, forecast_time_unit}; - if (*val % u2sf_step_unit != 0) { - err = grib_set_long_internal(h, self->step_units, forecast_time_unit); - *val = forecast_time_value; - return err; - } - *val = *val / u2sf_step_unit; - } - else - *val = forecast_time_value; + if ((err = grib_set_long_internal(h, "startStepUnit", UnitType{step_units}.to_long())) != GRIB_SUCCESS) + return err; + + *val = step.value(UnitType{step_units}); return GRIB_SUCCESS; } @@ -273,26 +252,31 @@ int pack_long_old_(grib_accessor* a, const long* val, size_t* len) { return grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_value, forecast_time_value); } -int pack_long_new_(grib_accessor* a, const long* val, size_t* len) { +int pack_long_new_(grib_accessor* a, const long start_step_value, const long start_step_unit) { grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); int err = 0; //long forecast_time_value; long forecast_time_unit; long step_units; - long start_step_value_old= 0; + long start_step_value_old; + long start_step_unit_old; + size_t len = 0; //long time_range_unit; //long time_range_value; if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit)) != GRIB_SUCCESS) return err; - if ((err = unpack_long(a, &start_step_value_old, len)) != GRIB_SUCCESS) + if ((err = unpack_long(a, &start_step_value_old, &len)) != GRIB_SUCCESS) return err; + if ((err = grib_get_long_internal(h, "startStepUnit", &start_step_unit_old)) != GRIB_SUCCESS) + return err; + //if ((err = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) //return err; - step_units = get_step_units(h); - Step start_step_old(start_step_value_old, step_units); - Step forecast_time(*val, step_units); + //step_units = get_step_units(h); + Step start_step_old(start_step_value_old, start_step_unit_old); + Step forecast_time(start_step_value, start_step_unit); Step time_range_new{}; auto time_range_opt = get_step(h, self->time_range_value, self->time_range_unit); @@ -302,12 +286,16 @@ int pack_long_new_(grib_accessor* a, const long* val, size_t* len) { auto [sa, sb] = find_common_units(forecast_time.optimize_unit(), time_range.optimize_unit()); if ((err = set_step(h, self->forecast_time_value, self->forecast_time_unit, sa)) != GRIB_SUCCESS) return err; + if ((err = grib_set_long_internal(h, "startStepUnit", forecast_time.unit().to_long())) != GRIB_SUCCESS) + return err; if ((err = set_step(h, self->time_range_value, self->time_range_unit, sb)) != GRIB_SUCCESS) return err; return GRIB_SUCCESS; } - + forecast_time.optimize_unit(); + if ((err = grib_set_long_internal(h, "startStepUnit", forecast_time.unit().to_long())) != GRIB_SUCCESS) + return err; if ((err = set_step(h, self->forecast_time_value, self->forecast_time_unit, forecast_time)) != GRIB_SUCCESS) return err; @@ -318,12 +306,17 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); int ret; - //if (is_future_output_enabled(h)) { - ret = pack_long_new_(a, val, len); - //} - //else { - // ret = pack_long_old_(a, val, len); - //} + //long step_units = UnitType{Unit::HOUR}.to_long(); + + + long start_step_unit; + if ((ret = grib_get_long_internal(h, "startStepUnit", &start_step_unit)) != GRIB_SUCCESS) + return ret; + + if (start_step_unit == 255) + start_step_unit = UnitType{Unit::HOUR}.to_long(); + + ret = pack_long_new_(a, *val, start_step_unit); return ret; } @@ -336,16 +329,8 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) size_t value_len = 0; Step step = step_from_string(val); - long step_units; - //if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) - // return ret; - step_units = get_step_units(h); - long value = step.value(); - - if ((ret = grib_set_long_internal(h, "stepUnits", step.unit().to_long())) != GRIB_SUCCESS) - return ret; - if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS) + if ((ret = pack_long_new_(a, step.value(), step.unit().to_long())) != GRIB_SUCCESS) return ret; return GRIB_SUCCESS; @@ -362,8 +347,6 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; long step_units; - //if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) - // return ret; step_units = get_step_units(h); Step step{value, step_units}; diff --git a/src/step.cc b/src/step.cc index 13ff22cd8..565f7b8ee 100644 --- a/src/step.cc +++ b/src/step.cc @@ -114,7 +114,6 @@ Step Step::operator-(const Step& step) const } -//std::pair find_common_units(const Step& startStep, const Step& endStep) std::pair find_common_units(const Step& startStep, const Step& endStep) { Step a = startStep; @@ -140,7 +139,6 @@ std::pair find_common_units(const Step& startStep, const Step& endSt b.recalculateValue(); } else { - // Find the highest common unit auto it = std::find_if(UnitType::unit_order_.begin(), UnitType::unit_order_.end(), [&](const auto& e) { return e == a.unit().to_value() || e == b.unit().to_value(); }); diff --git a/src/step_utilities.cc b/src/step_utilities.cc index 22b9929f7..4d98c5af8 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -47,9 +47,9 @@ long get_step_units(grib_handle* h) if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) throw std::runtime_error("Failed to get stepUnits"); - if (step_units == 255) { - if((ret = grib_get_long_internal(h, "optimalStepUnits", &step_units)) != GRIB_SUCCESS) - throw std::runtime_error("Failed to get optimalStepUnits"); - } + //if (step_units == 255) { + // if((ret = grib_get_long_internal(h, "optimalStepUnits", &step_units)) != GRIB_SUCCESS) + // throw std::runtime_error("Failed to get optimalStepUnits"); + //} return step_units; } diff --git a/src/step_utilities.h b/src/step_utilities.h index 9926f5938..5cb7dd6fa 100644 --- a/src/step_utilities.h +++ b/src/step_utilities.h @@ -8,26 +8,3 @@ std::optional get_step(grib_handle* h, const std::string& value_key, const bool is_future_output_enabled(grib_handle* h); int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step); long get_step_units(grib_handle* h); - -//template -//int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step) -//{ -// int err; -// if constexpr (std::is_same_v) { -// if ((err = grib_set_long_internal(h, value_key.c_str(), step.value())) != GRIB_SUCCESS) -// return err; -// } -// else if constexpr (std::is_same_v) { -// if ((err = grib_set_double_internal(h, value_key.c_str(), step.value())) != GRIB_SUCCESS) -// return err; -// } -// else { -// return GRIB_NOT_IMPLEMENTED; -// } - -// if ((err = grib_set_long_internal(h, unit_key.c_str(), step.unit().to_long())) != GRIB_SUCCESS) -// return err; -// return GRIB_SUCCESS; -//} - - diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 7be6a6df3..9a5dd0230 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -146,102 +146,102 @@ grib_check_key_equals $temp2 "-p stepRange:s" "1488-2928" fn="${data_dir}/reduced_gaussian_surface.grib2" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s" -keys__="step" +keys__="step,stepUnits:s" keys_s="step:s" -keys_i="step:i" -keys_d="step:d" +keys_i="step:i,stepUnits:s" +keys_d="step:d,stepUnits:s" ${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp -grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "3540" -grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "59" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "3540 s" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "59 m" #grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0" # TODO(EB): check behaviour (should be 0.983333) grib_check_key_equals $temp "-p $keys_s -s stepUnits=s" "3540s" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "59m" #grib_check_key_equals $temp "-p $keys_s -F"%.2f" -s stepUnits=h" "0.983333" # TODO(EB): check behaviour // See tools for default output format -grib_check_key_equals $temp "-p $keys_i -s stepUnits=s" "3540" -grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "59" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=s" "3540 s" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "59 m" #grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0" # TODO(EB): check behaviour -grib_check_key_equals $temp "-p $keys_d -s stepUnits=s" "3540" -grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "59" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=s" "3540 s" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "59 m" #grib_check_key_equals $temp "-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 "-p $keys_i -s stepUnits=s" "0" -grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "0" -grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0" -grib_check_key_equals $temp "-p $keys_d -s stepUnits=s" "0" -grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "0" -grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=s" "0 s" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "0 m" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0 h" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=s" "0 s" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "0 m" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0 h" 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" +keys__="step,stepUnits:s" +keys_s="step:s,stepUnits:s" +keys_i="step:i,stepUnits:s" +keys_d="step:d,stepUnits:s" ${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 "-p $keys_s" "0" -grib_check_key_equals $temp "-p $keys_i" "0" -grib_check_key_equals $temp "-p $keys_d" "0" +grib_check_key_equals $temp "-p $keys__" "0 m" +grib_check_key_equals $temp "-p $keys_s" "0m m" +grib_check_key_equals $temp "-p $keys_i" "0 m" +grib_check_key_equals $temp "-p $keys_d" "0 m" -grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "0" -grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "0" -grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0" -grib_check_key_equals $temp "-p $keys_s -s stepUnits=s" "0s" -grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "0m" -grib_check_key_equals $temp "-p $keys_s -s stepUnits=h" "0" -grib_check_key_equals $temp "-p $keys_i -s stepUnits=s" "0" -grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "0" -grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0" -grib_check_key_equals $temp "-p $keys_d -s stepUnits=s" "0" -grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "0" -grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "0 s" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "0 m" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0 h" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=s" "0s s" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "0m m" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=h" "0 h" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=s" "0 s" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "0 m" +grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0 h" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=s" "0 s" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "0 m" +grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0 h" ${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "59 m" -grib_check_key_equals $temp "-p $keys__" "59" +grib_check_key_equals $temp "-p $keys__" "59 m" #grib_check_key_equals $temp "-p $keys_s" "59" -grib_check_key_equals $temp "-p $keys_s" "59m" -grib_check_key_equals $temp "-p $keys_i" "59" -grib_check_key_equals $temp "-p $keys_d" "59" +grib_check_key_equals $temp "-p $keys_s" "59m m" +grib_check_key_equals $temp "-p $keys_i" "59 m" +grib_check_key_equals $temp "-p $keys_d" "59 m" ${tools_dir}/grib_set -s forecastTime=60,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m" -grib_check_key_equals $temp "-p $keys__" "1" -grib_check_key_equals $temp "-p $keys_s" "1" -grib_check_key_equals $temp "-p $keys_i" "1" -grib_check_key_equals $temp "-p $keys_d" "1" +grib_check_key_equals $temp "-p $keys__" "1 h" +grib_check_key_equals $temp "-p $keys_s" "1 h" +grib_check_key_equals $temp "-p $keys_i" "1 h" +grib_check_key_equals $temp "-p $keys_d" "1 h" ${tools_dir}/grib_set -s forecastTime=61,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "61 m" -grib_check_key_equals $temp "-p $keys__" "61" +grib_check_key_equals $temp "-p $keys__" "61 m" #grib_check_key_equals $temp "-p $keys_s" "61" -grib_check_key_equals $temp "-p $keys_s" "61m" -grib_check_key_equals $temp "-p $keys_i" "61" -grib_check_key_equals $temp "-p $keys_d" "61" +grib_check_key_equals $temp "-p $keys_s" "61m m" +grib_check_key_equals $temp "-p $keys_i" "61 m" +grib_check_key_equals $temp "-p $keys_d" "61 m" ${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "24 h" -grib_check_key_equals $temp "-p $keys__" "24" -grib_check_key_equals $temp "-p $keys_s" "24" -grib_check_key_equals $temp "-p $keys_i" "24" -grib_check_key_equals $temp "-p $keys_d" "24" +grib_check_key_equals $temp "-p $keys__" "24 h" +grib_check_key_equals $temp "-p $keys_s" "24 h" +grib_check_key_equals $temp "-p $keys_i" "24 h" +grib_check_key_equals $temp "-p $keys_d" "24 h" ${tools_dir}/grib_set -s forecastTime=1440,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "1440 m" -grib_check_key_equals $temp "-p $keys__" "24" -grib_check_key_equals $temp "-p $keys_s" "24" -grib_check_key_equals $temp "-p $keys_i" "24" -grib_check_key_equals $temp "-p $keys_d" "24" +grib_check_key_equals $temp "-p $keys__" "24 h" +grib_check_key_equals $temp "-p $keys_s" "24 h" +grib_check_key_equals $temp "-p $keys_i" "24 h" +grib_check_key_equals $temp "-p $keys_d" "24 h" From 24e3b4f4bb4299da81a99fcdbd65cdc2268f821c Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 15 Sep 2023 07:13:43 +0000 Subject: [PATCH 037/125] ECC-1620: Remove get_step_units() function --- src/grib_accessor_class_g2end_step.cc | 15 ++++++--------- src/grib_accessor_class_step_in_units.cc | 8 ++++---- src/step_utilities.cc | 15 --------------- src/step_utilities.h | 1 - 4 files changed, 10 insertions(+), 29 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index fa275eafd..539d03b55 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -281,9 +281,8 @@ static int unpack_one_time_range_long_(grib_accessor* a, long* val, size_t* len) if ((err = grib_get_long_internal(h, self->start_step_value, &start_step_value))) return err; - //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - //return err; - step_units = get_step_units(h); + if ((err = grib_get_long_internal(h, self->step_units, &step_units))) + return err; if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) return err; if ((err = grib_get_long_internal(h, self->time_range_value, &time_range_value))) @@ -329,9 +328,8 @@ static int unpack_multiple_time_ranges_long_(grib_accessor* a, long* val, size_t if ((err = grib_get_long_internal(h, self->start_step_value, &start_step_value))) return err; - //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - //return err; - step_units = get_step_units(h); + if ((err = grib_get_long_internal(h, self->step_units, &step_units))) + return err; if ((err = grib_get_long_internal(h, self->numberOfTimeRange, &numberOfTimeRange))) return err; if (numberOfTimeRange > MAX_NUM_TIME_RANGES) { @@ -576,9 +574,8 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; long step_units; - //if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) - //return ret; - step_units = get_step_units(h); + if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) + return ret; Step step(step_value, step_units); step.set_unit(step_units); diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 4e2d3c17b..78259360b 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -209,9 +209,8 @@ int pack_long_old_(grib_accessor* a, const long* val, size_t* len) { if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) return err; - //if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - // return err; - step_units = get_step_units(h); + if ((err = grib_get_long_internal(h, self->step_units, &step_units))) + return err; unpack_long(a, &oldStep, len); @@ -347,7 +346,8 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; long step_units; - step_units = get_step_units(h); + if ((ret = grib_get_long_internal(h, self->step_units, &step_units))) + return ret; Step step{value, step_units}; step.hide_hour_unit(); diff --git a/src/step_utilities.cc b/src/step_utilities.cc index 4d98c5af8..51dc3dbc1 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -38,18 +38,3 @@ bool is_future_output_enabled(grib_handle* h) { return h->context->is_future_step_format > 0; } - - -long get_step_units(grib_handle* h) -{ - int ret = 0; - long step_units = 0; - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) - throw std::runtime_error("Failed to get stepUnits"); - - //if (step_units == 255) { - // if((ret = grib_get_long_internal(h, "optimalStepUnits", &step_units)) != GRIB_SUCCESS) - // throw std::runtime_error("Failed to get optimalStepUnits"); - //} - return step_units; -} diff --git a/src/step_utilities.h b/src/step_utilities.h index 5cb7dd6fa..da70bec94 100644 --- a/src/step_utilities.h +++ b/src/step_utilities.h @@ -7,4 +7,3 @@ std::optional get_step(grib_handle* h, const std::string& value_key, const std::string& unit_key); bool is_future_output_enabled(grib_handle* h); int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step); -long get_step_units(grib_handle* h); From 32aceb86a08d185d834e256452bd54938d962386 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 15 Sep 2023 11:34:16 +0000 Subject: [PATCH 038/125] ECC-1620: Bug fixes --- src/grib_accessor_class_step_in_units.cc | 5 ++++- src/step.cc | 5 +++-- src/step.h | 8 +++++++- src/step_utilities.cc | 10 +++++----- src/step_utilities.h | 2 +- tests/grib_ecc-1620.sh | 13 +++++++++++++ 6 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 78259360b..868f46b24 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -191,7 +191,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) Step step{forecast_time_value, forecast_time_unit}; if ((err = grib_set_long_internal(h, "startStepUnit", UnitType{step_units}.to_long())) != GRIB_SUCCESS) - return err; + return err; *val = step.value(UnitType{step_units}); @@ -279,9 +279,12 @@ int pack_long_new_(grib_accessor* a, const long start_step_value, const long sta Step time_range_new{}; auto time_range_opt = get_step(h, self->time_range_value, self->time_range_unit); + if (time_range_opt) { auto time_range = time_range_opt.value(); time_range = time_range - (forecast_time - start_step_old); + if (time_range.value() < 0) + time_range = Step{0l, time_range.unit()}; auto [sa, sb] = find_common_units(forecast_time.optimize_unit(), time_range.optimize_unit()); if ((err = set_step(h, self->forecast_time_value, self->forecast_time_unit, sa)) != GRIB_SUCCESS) return err; diff --git a/src/step.cc b/src/step.cc index 565f7b8ee..18d72a594 100644 --- a/src/step.cc +++ b/src/step.cc @@ -50,7 +50,8 @@ Step step_from_string(std::string step) if (unit.size() == 0) { unit = "h"; } - return Step{std::stod(value), UnitType{unit}}; + Step ret{std::stod(value), UnitType{unit}}; + return ret; } } throw std::runtime_error("Could not parse step: " + step); @@ -176,7 +177,7 @@ void Step::init_double(double value, const UnitType& unit) { long seconds = UnitType::get_converter().unit_to_duration(unit.to_value()); init_long(static_cast(value * seconds), UnitType{Unit::SECOND}); - optimize_unit(); + unit_ = unit; } Step& Step::optimize_unit() diff --git a/src/step.h b/src/step.h index a5d6d5343..481007767 100644 --- a/src/step.h +++ b/src/step.h @@ -195,7 +195,13 @@ public: Step operator-(const Step& step) const; bool operator>(const Step& step) const; bool operator<(const Step& step) const; - Step copy() const {return Step{internal_value_, internal_unit_};} + Step copy() const { + Step ret{}; + ret.internal_value_ = internal_value_; + ret.internal_unit_ = internal_unit_; + ret.unit_ = unit_; + return ret; + } // Methods Step& optimize_unit(); diff --git a/src/step_utilities.cc b/src/step_utilities.cc index 51dc3dbc1..d46d1900e 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -2,15 +2,15 @@ #include -std::optional get_step(grib_handle* h, const std::string& value_key, const std::string& unit_key) +std::optional get_step(grib_handle* h, const char* value_key, const char* unit_key) { - if (grib_is_defined(h, unit_key.c_str()) && grib_is_defined(h, value_key.c_str())) { + if (value_key && unit_key && grib_is_defined(h, unit_key) && grib_is_defined(h, value_key)) { long unit = 0; - if (grib_get_long_internal(h, unit_key.c_str(), &unit) != GRIB_SUCCESS) + if (grib_get_long_internal(h, unit_key, &unit) != GRIB_SUCCESS) return {}; long value = 0; - if (grib_get_long_internal(h, value_key.c_str(), &value) != GRIB_SUCCESS) + if (grib_get_long_internal(h, value_key, &value) != GRIB_SUCCESS) return {}; return Step(value, unit); @@ -25,7 +25,7 @@ int set_step(grib_handle* h, const std::string& value_key, const std::string& un { int err; Step step_copy = step.copy(); - step_copy.optimize_unit(); + //step_copy.optimize_unit(); if ((err = grib_set_long_internal(h, value_key.c_str(), step_copy.value())) != GRIB_SUCCESS) return err; if ((err = grib_set_long_internal(h, unit_key.c_str(), step_copy.unit().to_long())) != GRIB_SUCCESS) diff --git a/src/step_utilities.h b/src/step_utilities.h index da70bec94..5259a0ed3 100644 --- a/src/step_utilities.h +++ b/src/step_utilities.h @@ -4,6 +4,6 @@ #include "step.h" #include -std::optional get_step(grib_handle* h, const std::string& value_key, const std::string& unit_key); +std::optional get_step(grib_handle* h, const char* value_key, const char* unit_key); bool is_future_output_enabled(grib_handle* h); int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step); diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 9a5dd0230..cc97118da 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -46,6 +46,19 @@ temp2=temp_2.$label +#### CHECK: check optimal units are set correctly in GRIB files +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" + +${tools}/grib_set -s startStep:i=60,endStep:i=180,stepUnits:s=s $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" +${tools}/grib_set -s startStep:i=60,endStep:i=180,stepUnits:s=m $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "1 h 2 h" +${tools}/grib_set -s startStep:i=60,endStep:i=180,stepUnits:s=h $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "60 h 180 h" + #fn="${data_dir}/reduced_gaussian_sub_area.grib2" #low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" From 5392a164b05dbde6102faa4e5c70e745dabb39bf Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Tue, 19 Sep 2023 09:44:35 +0000 Subject: [PATCH 039/125] ECC-1620: Fix stepUnits --- .../grib2/template.4.forecast_time.def | 3 ++- src/grib_accessor_class_g2end_step.cc | 19 ++++++++++++----- src/grib_accessor_class_optimal_step_units.cc | 19 ++++++++++------- src/grib_accessor_class_step_in_units.cc | 21 ++++++++++++------- tests/grib_ecc-1620.sh | 16 ++++++++++---- 5 files changed, 53 insertions(+), 25 deletions(-) diff --git a/definitions/grib2/template.4.forecast_time.def b/definitions/grib2/template.4.forecast_time.def index 2c0372e36..837c41fa1 100644 --- a/definitions/grib2/template.4.forecast_time.def +++ b/definitions/grib2/template.4.forecast_time.def @@ -14,7 +14,8 @@ codetable[1] indicatorOfUnitOfTimeRange ('4.4.table',masterDir,localDir) : dump #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; +meta stepUnits optimal_step_units(forecastTime,indicatorOfUnitOfTimeRange,lengthOfTimeRange,indicatorOfUnitForTimeRange) : transient,dump; +transient forceStepUnits = 255; transient startStepUnit = 255; transient endStepUnit = 255; diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 539d03b55..9b73d4c78 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -536,7 +536,7 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en //auto [forecast_time, time_range] = find_common_units(Step{forecast_time_value, forecast_time_unit}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); //auto [forecast_time, time_range] = find_common_units(Step{start_step_value, step_units}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); - auto [forecast_time_opt, time_range_opt] = find_common_units(start_step, time_range); + auto [forecast_time_opt, time_range_opt] = find_common_units(start_step.optimize_unit(), time_range.optimize_unit()); if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range_opt.value())) != GRIB_SUCCESS) return err; @@ -592,12 +592,21 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int ret; - long end_step_unit; - if ((ret = grib_get_long_internal(h, "endStepUnit", &end_step_unit)) != GRIB_SUCCESS) + long force_step_units; + if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) return ret; - if (end_step_unit == 255) - end_step_unit = UnitType{Unit::HOUR}.to_long(); + long end_step_unit; + if (force_step_units == 255) { + if ((ret = grib_get_long_internal(h, "endStepUnit", &end_step_unit)) != GRIB_SUCCESS) + return ret; + + if (end_step_unit == 255) + end_step_unit = UnitType{Unit::HOUR}.to_long(); + } + else { + end_step_unit = force_step_units; + } return pack_long_(a, *val, end_step_unit); } diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 20ff3b1be..9a828e8d6 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -22,7 +22,7 @@ CLASS = accessor SUPER = grib_accessor_class_gen IMPLEMENTS = pack_long,unpack_long;dump - IMPLEMENTS = unpack_string,unpack_string;dump + IMPLEMENTS = pack_string,unpack_string;dump IMPLEMENTS = string_length IMPLEMENTS = init MEMBERS = const char* forecast_time_value @@ -137,22 +137,24 @@ static void dump(grib_accessor* a, grib_dumper* dumper) } -//static int value_count(grib_accessor* a, long* count) -//{ - //*count = 1; - //return 0; -//} - static size_t string_length(grib_accessor* a) { return 255; } static long staticStepUnits = UnitType{Unit::MISSING}.to_long(); +static long staticForceStepUnits = UnitType{Unit::MISSING}.to_long(); static int pack_long(grib_accessor* a, const long* val, size_t* len) { + grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; + grib_handle* h = grib_handle_of_accessor(a); + + int ret; staticStepUnits = *val; + if ((ret = grib_set_long_internal(h, "forceStepUnits", *val)) != GRIB_SUCCESS) { + return ret; + } return GRIB_SUCCESS; } @@ -189,7 +191,8 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { - staticStepUnits = UnitType{val}.to_long(); + long unit = UnitType{val}.to_long(); + pack_long(a, &unit, len); return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 868f46b24..cdf8eb2bd 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -279,7 +279,7 @@ int pack_long_new_(grib_accessor* a, const long start_step_value, const long sta Step time_range_new{}; auto time_range_opt = get_step(h, self->time_range_value, self->time_range_unit); - + if (time_range_opt) { auto time_range = time_range_opt.value(); time_range = time_range - (forecast_time - start_step_old); @@ -308,15 +308,22 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); int ret; - //long step_units = UnitType{Unit::HOUR}.to_long(); - - long start_step_unit; - if ((ret = grib_get_long_internal(h, "startStepUnit", &start_step_unit)) != GRIB_SUCCESS) + long force_step_units; + if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) return ret; - if (start_step_unit == 255) - start_step_unit = UnitType{Unit::HOUR}.to_long(); + long start_step_unit; + if (force_step_units == 255) { + if ((ret = grib_get_long_internal(h, "startStepUnit", &start_step_unit)) != GRIB_SUCCESS) + return ret; + + if (start_step_unit == 255) + start_step_unit = UnitType{Unit::HOUR}.to_long(); + } + else { + start_step_unit = force_step_units; + } ret = pack_long_new_(a, *val, start_step_unit); diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index cc97118da..8dd22a0e5 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -52,12 +52,20 @@ low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indi ${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" -${tools}/grib_set -s startStep:i=60,endStep:i=180,stepUnits:s=s $temp $temp2 +${tools_dir}/grib_set -s stepUnits:i=13,startStep:i=60,endStep:i=180 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" -${tools}/grib_set -s startStep:i=60,endStep:i=180,stepUnits:s=m $temp $temp2 +${tools_dir}/grib_set -s stepUnits:s=s,startStep:i=60,endStep:i=180 $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" + +${tools_dir}/grib_set -s stepUnits:i=0,startStep:i=60,endStep:i=180 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "1 h 2 h" -${tools}/grib_set -s startStep:i=60,endStep:i=180,stepUnits:s=h $temp $temp2 -grib_check_key_equals $temp2 "-p $low_level_keys" "60 h 180 h" +${tools_dir}/grib_set -s stepUnits:s=m,startStep:i=60,endStep:i=180 $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "1 h 2 h" + +${tools_dir}/grib_set -s stepUnits:i=1,startStep:i=60,endStep:i=180 $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "60 h 120 h" +${tools_dir}/grib_set -s stepUnits:s=h,startStep:i=60,endStep:i=180 $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "60 h 120 h" #fn="${data_dir}/reduced_gaussian_sub_area.grib2" From 3a39398462882e90e1cd8146df7e8cdc35cf4aaf Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Tue, 19 Sep 2023 09:58:04 +0000 Subject: [PATCH 040/125] ECC-1620: Add stepUnits to MARS output --- definitions/grib1/section.1.def | 1 + definitions/grib2/products_s2s.def | 1 + definitions/grib2/template.4.localtime.def | 2 +- definitions/grib2/template.4.point_in_time.def | 1 + definitions/grib2/template.4.statistical.def | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/definitions/grib1/section.1.def b/definitions/grib1/section.1.def index 0a1985904..4a930af5d 100644 --- a/definitions/grib1/section.1.def +++ b/definitions/grib1/section.1.def @@ -224,6 +224,7 @@ alias ls.stepRange = stepRange; alias ls.dataDate = dataDate; alias mars.step = endStep; +alias mars.stepUnits = stepUnits; alias mars.date = dataDate; alias mars.levtype = indicatorOfTypeOfLevel; alias mars.time = dataTime; diff --git a/definitions/grib2/products_s2s.def b/definitions/grib2/products_s2s.def index 13c90fb72..a20c733ee 100644 --- a/definitions/grib2/products_s2s.def +++ b/definitions/grib2/products_s2s.def @@ -73,6 +73,7 @@ alias mars.type = marsType; # Normally MARS step is endStep but for monthly means we want stepRange if (stepType is "avg") { alias mars.step = stepRange; + alias mars.stepUnits = stepUnits; } if (isHindcast == 1) { diff --git a/definitions/grib2/template.4.localtime.def b/definitions/grib2/template.4.localtime.def index 01491217c..a9ea6a8a3 100644 --- a/definitions/grib2/template.4.localtime.def +++ b/definitions/grib2/template.4.localtime.def @@ -82,7 +82,7 @@ if (numberOfForecastsUsedInLocalTime == 1) { alias mars.date = dateOfForecastUsedInLocalTime : dump; alias mars.time = timeOfForecastUsedInLocalTime : dump; alias mars.step = endStep; - + alias mars.stepUnits = stepUnits; alias time.dataDate = dateOfForecastUsedInLocalTime; alias time.dataTime = timeOfForecastUsedInLocalTime; alias time.endStep = endStep; diff --git a/definitions/grib2/template.4.point_in_time.def b/definitions/grib2/template.4.point_in_time.def index f2e8606fd..61d939991 100644 --- a/definitions/grib2/template.4.point_in_time.def +++ b/definitions/grib2/template.4.point_in_time.def @@ -7,6 +7,7 @@ alias step=startStep; alias marsStep=startStep; alias mars.step=startStep; +alias mars.stepUnits=stepUnits; alias marsStartStep = startStep; alias marsEndStep = endStep; diff --git a/definitions/grib2/template.4.statistical.def b/definitions/grib2/template.4.statistical.def index 63545eea0..d68b54efd 100644 --- a/definitions/grib2/template.4.statistical.def +++ b/definitions/grib2/template.4.statistical.def @@ -112,6 +112,7 @@ if (numberOfTimeRange == 1 || numberOfTimeRange == 2) { alias ls.stepRange=stepRange; alias mars.step=endStep; +alias mars.stepUnits=stepUnits; alias time.stepType=stepType; alias time.stepRange=stepRange; From 9309bae15465127967cbef4f1a34a5cf26975dc1 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Tue, 19 Sep 2023 12:04:38 +0000 Subject: [PATCH 041/125] ECC-1620: Support decimal steps --- src/grib_accessor_class_g2end_step.cc | 152 ++++++++++++++++++++++- src/grib_accessor_class_g2step_range.cc | 77 +++++++----- src/grib_accessor_class_step_in_units.cc | 32 ++++- 3 files changed, 230 insertions(+), 31 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 9b73d4c78..83fe53247 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -20,6 +20,7 @@ CLASS = accessor SUPER = grib_accessor_class_long IMPLEMENTS = unpack_long;pack_long + IMPLEMENTS = unpack_double IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = init;dump MEMBERS = const char* start_step_value // startStep @@ -61,6 +62,7 @@ or edit "accessor.class" and rerun ./make_class.pl 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_long(grib_accessor*, long* val, size_t* len); +static int unpack_double(grib_accessor*, double* 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*); @@ -116,7 +118,7 @@ static grib_accessor_class _grib_accessor_class_g2end_step = { &unpack_long, /* unpack_long */ 0, /* pack_double */ 0, /* pack_float */ - 0, /* unpack_double */ + &unpack_double, /* unpack_double */ 0, /* unpack_float */ &pack_string, /* pack_string */ &unpack_string, /* unpack_string */ @@ -267,6 +269,7 @@ static int convert_time_range_long_( } + static int unpack_one_time_range_long_(grib_accessor* a, long* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; @@ -313,6 +316,55 @@ static int unpack_one_time_range_long_(grib_accessor* a, long* val, size_t* len) } +static int unpack_one_time_range_double_(grib_accessor* a, double *val , size_t* len) +{ + grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; + int err = 0; + double start_step_value; + long start_step_unit; + long step_units; + long time_range_unit; + double time_range_value; + long typeOfTimeIncrement; + int add_time_range = 1; /* whether we add lengthOfTimeRange */ + + grib_handle* h = grib_handle_of_accessor(a); + + if ((err = grib_get_double_internal(h, self->start_step_value, &start_step_value))) + return err; + if ((err = grib_get_long_internal(h, "startStepUnit", &start_step_unit))) + return err; + if ((err = grib_get_long_internal(h, self->step_units, &step_units))) + return err; + if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit))) + return err; + if ((err = grib_get_double_internal(h, self->time_range_value, &time_range_value))) + return err; + if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement))) + return err; + + Step start_step{start_step_value, start_step_unit}; + Step time_range{time_range_value, time_range_unit}; + + if (typeOfTimeIncrement == 1) { + /* See GRIB-488 */ + /* Note: For this case, lengthOfTimeRange is not related to step and should not be used to calculate step */ + add_time_range = 0; + if (is_special_expver(h)) { + add_time_range = 1; + } + } + if (add_time_range) { + *val = (start_step + time_range).value(UnitType(step_units)); + } + else { + *val = start_step.value(UnitType(start_step_unit)); + } + + return GRIB_SUCCESS; +} + + #define MAX_NUM_TIME_RANGES 16 /* maximum number of time range specifications */ static int unpack_multiple_time_ranges_long_(grib_accessor* a, long* val, size_t* len) { @@ -368,6 +420,69 @@ static int unpack_multiple_time_ranges_long_(grib_accessor* a, long* val, size_t } + +static int unpack_multiple_time_ranges_double_(grib_accessor* a, double* val, size_t* len) +{ + grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; + int i = 0, err = 0; + grib_handle* h = grib_handle_of_accessor(a); + long numberOfTimeRange = 0; + long step_units = 0; + long start_step_value = 0; + long start_step_unit = 0; + + size_t count = 0; + long arr_typeOfTimeIncrement[MAX_NUM_TIME_RANGES] = {0, }; + long arr_coded_unit[MAX_NUM_TIME_RANGES] = {0, }; + long arr_coded_time_range[MAX_NUM_TIME_RANGES] = {0, }; + + if ((err = grib_get_long_internal(h, self->start_step_value, &start_step_value))) + return err; + if ((err = grib_get_long_internal(h, "startStepUnit", &start_step_unit))) + return err; + + Step start_step{start_step_value, start_step_unit}; + + if ((err = grib_get_long_internal(h, self->step_units, &step_units))) + return err; + + if ((err = grib_get_long_internal(h, self->numberOfTimeRange, &numberOfTimeRange))) + return err; + if (numberOfTimeRange > MAX_NUM_TIME_RANGES) { + grib_context_log(h->context, GRIB_LOG_ERROR, "Too many time range specifications!"); + return GRIB_DECODING_ERROR; + } + + count = numberOfTimeRange; + /* Get the arrays for the N time ranges */ + if ((err = grib_get_long_array(h, self->typeOfTimeIncrement, arr_typeOfTimeIncrement, &count))) + return err; + if ((err = grib_get_long_array(h, self->time_range_unit, arr_coded_unit, &count))) + return err; + if ((err = grib_get_long_array(h, self->time_range_value, arr_coded_time_range, &count))) + return err; + + /* Look in the array of typeOfTimeIncrements for first entry whose typeOfTimeIncrement == 2 */ + for (i = 0; i < count; i++) { + if (arr_typeOfTimeIncrement[i] == 2) { + /* Found the required time range. Get the other two keys from it */ + long the_coded_unit = arr_coded_unit[i]; + long the_coded_time_range = arr_coded_time_range[i]; + + Step time_range{the_coded_unit, the_coded_time_range}; + *val = (start_step + time_range).value(UnitType(step_units)); + + return GRIB_SUCCESS; + } + } + + grib_context_log(h->context, GRIB_LOG_ERROR, + "Cannot calculate endStep. No time range specification with typeOfTimeIncrement = 2"); + return GRIB_DECODING_ERROR; +} + + + // For the old implementation of unpack_long, see // src/deprecated/grib_accessor_class_g2end_step.unpack_long.cc // @@ -406,6 +521,41 @@ static int unpack_long(grib_accessor* a, long* 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 start_step_value; + long numberOfTimeRange; + + if ((ret = grib_get_long_internal(h, self->start_step_value, &start_step_value))) + return ret; + + /* point in time */ + if (self->year == NULL) { + *val = start_step_value; + return 0; + } + + Assert(self->numberOfTimeRange); + if ((ret = grib_get_long_internal(h, self->numberOfTimeRange, &numberOfTimeRange))) + return ret; + Assert(numberOfTimeRange == 1 || numberOfTimeRange == 2); + + if (numberOfTimeRange == 1) { + ret = unpack_one_time_range_double_(a, val, len); + return ret; + } + else { + ret = unpack_multiple_time_ranges_double_(a, val, len); + return ret; + } + + return GRIB_SUCCESS; +} + + static int pack_long_(grib_accessor* a, const long end_step_value, const long end_step_unit) { diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 580452eca..da5917860 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -140,11 +140,11 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) char buf[100]; int ret = 0; size_t size = 0; - long start_step_value = 0; - long end_step_value = 0; + double start_step_value = 0; + double end_step_value = 0; long step_units; - if ((ret = grib_get_long_internal(h, self->start_step, &start_step_value)) != GRIB_SUCCESS) + if ((ret = grib_get_double_internal(h, self->start_step, &start_step_value)) != GRIB_SUCCESS) return ret; if ((ret= grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; @@ -157,36 +157,20 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) Step start_step{start_step_value, step_units}; start_step.hide_hour_unit(); if (self->end_step == NULL) { - //if (is_future_output_enabled(h)) { - snprintf(buf, sizeof(buf), "%s", start_step.to_string().c_str()); - //} - //else { - // snprintf(buf, sizeof(buf), "%ld", start_step_value); - //} + snprintf(buf, sizeof(buf), "%s", start_step.to_string().c_str()); } else { - if ((ret = grib_get_long_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) + if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) return ret; - //if (is_future_output_enabled(h)) { - Step end_step{end_step_value, step_units}; - end_step.hide_hour_unit(); - if (start_step_value == end_step_value) { - snprintf(buf, sizeof(buf), "%s", end_step.to_string().c_str()); - } - else { - snprintf(buf, sizeof(buf), "%s-%s", start_step.to_string().c_str(), end_step.to_string().c_str()); - } - //} - //else { - // if (start_step_value == end_step_value) { - // snprintf(buf, sizeof(buf), "%ld", end_step_value); - // } - // else { - // snprintf(buf, sizeof(buf), "%ld-%ld", start_step_value, end_step_value); - // } - //} - + Step end_step{end_step_value, step_units}; + end_step.hide_hour_unit(); + if (start_step_value == end_step_value) { + snprintf(buf, sizeof(buf), "%s", end_step.to_string().c_str()); + } + else { + snprintf(buf, sizeof(buf), "%s-%s", start_step.to_string().c_str(), end_step.to_string().c_str()); + } } size = strlen(buf) + 1; @@ -320,6 +304,41 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) return GRIB_SUCCESS; } + +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); + int ret = 0; + double end_start_value = 0; + double end_step_value = 0; + long step_units = 0; + + if ((ret = grib_get_double_internal(h, self->start_step, &end_start_value)) != GRIB_SUCCESS) + return ret; + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + throw std::runtime_error("Failed to get stepUnits"); + if (step_units == 255) { + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + return ret; + } + + Step start_step{end_start_value, step_units}; + start_step.hide_hour_unit(); + if (self->end_step == NULL) { + *val = start_step.value(); + } + else { + if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) + return ret; + Step end_step{end_step_value, step_units}; + *val = end_step.value(); + } + + return GRIB_SUCCESS; +} + + static int get_native_type(grib_accessor* a) { return GRIB_TYPE_STRING; diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index cdf8eb2bd..678a28bcf 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -19,6 +19,7 @@ CLASS = accessor SUPER = grib_accessor_class_long IMPLEMENTS = unpack_long;pack_long + IMPLEMENTS = unpack_double IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = init;dump MEMBERS = const char* forecast_time_value @@ -44,6 +45,7 @@ or edit "accessor.class" and rerun ./make_class.pl 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_long(grib_accessor*, long* val, size_t* len); +static int unpack_double(grib_accessor*, double* 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*); @@ -86,7 +88,7 @@ static grib_accessor_class _grib_accessor_class_step_in_units = { &unpack_long, /* unpack_long */ 0, /* pack_double */ 0, /* pack_float */ - 0, /* unpack_double */ + &unpack_double, /* unpack_double */ 0, /* unpack_float */ &pack_string, /* pack_string */ &unpack_string, /* unpack_string */ @@ -199,6 +201,34 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) } + +static int unpack_double(grib_accessor* a, double * val, size_t* len) +{ + grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; + int err = 0; + long forecast_time_value, forecast_time_unit, step_units; + grib_handle* h = grib_handle_of_accessor(a); + int factor = 0; + long u2sf, u2sf_step_unit; + + if ((err= grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + return err; + if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) + return err; + if ((err = grib_get_long_internal(h, self->forecast_time_value, &forecast_time_value))) + return err; + + Step step{forecast_time_value, forecast_time_unit}; + + if ((err = grib_set_long_internal(h, "startStepUnit", UnitType{step_units}.to_long())) != GRIB_SUCCESS) + return err; + + *val = step.value(UnitType{step_units}); + + return GRIB_SUCCESS; +} + + int pack_long_old_(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); From 0bd065768096b0aa585399f675ea03559ee3892d Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 20 Sep 2023 13:56:38 +0000 Subject: [PATCH 042/125] ECC-1620: Format decimal values --- definitions/boot.def | 1 + definitions/grib2/boot.def | 1 + .../grib2/template.4.forecast_time.def | 5 +-- src/grib_accessor_class_g2end_step.cc | 29 ++++++++++---- src/grib_accessor_class_g2step_range.cc | 22 +++++----- src/grib_accessor_class_step_in_units.cc | 38 +++++++++++------- src/step.cc | 2 + src/step.h | 40 ++++++++----------- tests/grib_ecc-1212.sh | 1 + tests/grib_mars_keys.sh | 2 + tools/grib_options.cc | 2 +- tools/grib_tools.cc | 27 +++++++------ 12 files changed, 99 insertions(+), 71 deletions(-) diff --git a/definitions/boot.def b/definitions/boot.def index 22edf96e1..683f21a37 100644 --- a/definitions/boot.def +++ b/definitions/boot.def @@ -52,6 +52,7 @@ transient unitsFactor=1 : hidden; transient unitsBias=0 : hidden; constant globalDomain = "g"; transient timeRangeIndicatorFromStepRange=-1 : hidden; +transient format = "%g" : hidden; # ECC-868 transient produceLargeConstantFields = 0 : hidden; diff --git a/definitions/grib2/boot.def b/definitions/grib2/boot.def index 0a16b2893..4157806d2 100644 --- a/definitions/grib2/boot.def +++ b/definitions/grib2/boot.def @@ -42,3 +42,4 @@ template core "grib2/sections.def"; #} template section_8 "grib2/section.8.def"; +transient forceStepUnits = 255 : hidden; diff --git a/definitions/grib2/template.4.forecast_time.def b/definitions/grib2/template.4.forecast_time.def index 837c41fa1..d8c8b8cce 100644 --- a/definitions/grib2/template.4.forecast_time.def +++ b/definitions/grib2/template.4.forecast_time.def @@ -15,9 +15,8 @@ codetable[1] indicatorOfUnitOfTimeRange ('4.4.table',masterDir,localDir) : dump #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) : transient,dump; -transient forceStepUnits = 255; -transient startStepUnit = 255; -transient endStepUnit = 255; +transient startStepUnit = 255 : hidden; +transient endStepUnit = 255 : hidden; # Forecast time in units defined by previous octet (GRIB-29: supports negative forecast time) signed[4] forecastTime : dump; diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 83fe53247..b5e814172 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -625,7 +625,7 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if (time_range.value() < 0) { grib_context_log(h->context, GRIB_LOG_ERROR, - "endStep < startStep (%s < %s)", end_step.to_string().c_str(), start_step.to_string().c_str()); + "endStep < startStep (%s < %s)", end_step.to_string("%g").c_str(), start_step.to_string("%g").c_str()); return GRIB_WRONG_STEP; } @@ -716,22 +716,35 @@ 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; - - - long step_value; + size_t fp_format_len = 128; + char fp_format[128]; size_t step_len = 0; + long step_value; + long step_units; + + if ((ret = unpack_long(a, &step_value, &step_len)) != GRIB_SUCCESS) return ret; - - long step_units; if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) return ret; + if ((ret = grib_get_string_internal(h, "format", fp_format, &fp_format_len)) != GRIB_SUCCESS) + return ret; Step step(step_value, step_units); step.set_unit(step_units); - step.hide_hour_unit(); - snprintf(val, *len, "%s", step.to_string().c_str()); + std::stringstream ss; + + ss << step.to_string(fp_format); + + size_t size = ss.str().size() + 1; + + if (*len < size) + return GRIB_ARRAY_TOO_SMALL; + + *len = size; + + memcpy(val, ss.str().c_str(), size); return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index da5917860..3d4e61228 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -16,6 +16,7 @@ #include "step.h" #include "step_utilities.h" #include +#include /* This is used by make_class.pl @@ -154,33 +155,38 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) } + size_t fp_format_len = 128; + char fp_format[128]; + if ((ret = grib_get_string_internal(h, "format", fp_format, &fp_format_len)) != GRIB_SUCCESS) + return ret; + std::stringstream ss; + Step start_step{start_step_value, step_units}; - start_step.hide_hour_unit(); if (self->end_step == NULL) { - snprintf(buf, sizeof(buf), "%s", start_step.to_string().c_str()); + ss << start_step.to_string(fp_format); } else { if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) return ret; Step end_step{end_step_value, step_units}; - end_step.hide_hour_unit(); + if (start_step_value == end_step_value) { - snprintf(buf, sizeof(buf), "%s", end_step.to_string().c_str()); + ss << end_step.to_string(fp_format); } else { - snprintf(buf, sizeof(buf), "%s-%s", start_step.to_string().c_str(), end_step.to_string().c_str()); + ss << start_step.to_string(fp_format) << "-" << end_step.to_string(fp_format); } } - size = strlen(buf) + 1; + size = ss.str().size() + 1; if (*len < size) return GRIB_ARRAY_TOO_SMALL; *len = size; - memcpy(val, buf, size); + memcpy(val, ss.str().c_str(), size); return GRIB_SUCCESS; } @@ -290,7 +296,6 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) } Step start_step{end_start_value, step_units}; - start_step.hide_hour_unit(); if (self->end_step == NULL) { *val = start_step.value(); } @@ -324,7 +329,6 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) } Step start_step{end_start_value, step_units}; - start_step.hide_hour_unit(); if (self->end_step == NULL) { *val = start_step.value(); } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 678a28bcf..74f2cce34 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -380,25 +380,35 @@ 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; - long value; - size_t value_len; - if ((ret = unpack_long(a, &value, &value_len)) != GRIB_SUCCESS) - return ret; - + long start_step_value; + long start_step_unit; long step_units; + size_t fp_format_len = 128; + char fp_format[128]; + + if ((ret = grib_get_long_internal(h, "startStep", &start_step_value)) != GRIB_SUCCESS) + return ret; + if ((ret = grib_get_long_internal(h, "startStepUnit", &start_step_unit)) != GRIB_SUCCESS) + return ret; if ((ret = grib_get_long_internal(h, self->step_units, &step_units))) return ret; + if ((ret = grib_get_string_internal(h, "format", fp_format, &fp_format_len)) != GRIB_SUCCESS) + return ret; - Step step{value, step_units}; - step.hide_hour_unit(); - //snprintf(val, *len, "%ld", value); + Step step{start_step_value, start_step_unit}; + std::stringstream ss; + + ss << step.to_string(fp_format); + + size_t size = ss.str().size() + 1; + + if (*len < size) + return GRIB_ARRAY_TOO_SMALL; + + *len = size; + + memcpy(val, ss.str().c_str(), size); - //if (is_future_output_enabled(h)) { - snprintf(val, *len, "%s", step.to_string().c_str()); - //} - //else { - // snprintf(val, *len, "%ld", step.value()); - //} return GRIB_SUCCESS; } diff --git a/src/step.cc b/src/step.cc index 18d72a594..f4f710561 100644 --- a/src/step.cc +++ b/src/step.cc @@ -170,6 +170,7 @@ void Step::init_long(long value, const UnitType& unit) internal_value_ = value; internal_unit_ = unit; unit_ = internal_unit_; + //unit_.hide_hour_unit(); sanity_check(); } @@ -178,6 +179,7 @@ void Step::init_double(double value, const UnitType& unit) long seconds = UnitType::get_converter().unit_to_duration(unit.to_value()); init_long(static_cast(value * seconds), UnitType{Unit::SECOND}); unit_ = unit; + //unit_.hide_hour_unit(); } Step& Step::optimize_unit() diff --git a/src/step.h b/src/step.h index 481007767..ed5d9b69c 100644 --- a/src/step.h +++ b/src/step.h @@ -73,22 +73,15 @@ public: } std::string to_string() const { - if ((internal_value_ == Unit::HOUR) && hide_hour_unit_) { - return ""; - } - else { - return map_.unit_to_name(internal_value_); - } + return map_.unit_to_name(internal_value_); } + long to_long() const {return map_.unit_to_long(internal_value_);} Unit to_value() const {return internal_value_;} - void hide_hour_unit() {hide_hour_unit_ = true;} - void show_hour_unit() {hide_hour_unit_ = false;} static std::vector unit_order_; static std::vector complete_unit_order_; private: - bool hide_hour_unit_ = false; class Map { public: Map() { @@ -206,23 +199,22 @@ public: // Methods Step& optimize_unit(); friend std::pair find_common_units(const Step& startStep, const Step& endStep); - void hide_hour_unit() { - internal_unit_.hide_hour_unit(); - unit_.hide_hour_unit(); - } - void show_hour_unit() { - internal_unit_.show_hour_unit(); - unit_.show_hour_unit(); - } - std::string to_string() const { - std::stringstream ss; - if (value() == value()) { - ss << value() << unit_.to_string(); - } else { - ss << value() << unit_.to_string(); + std::string to_string(const std::string& format) const { + constexpr int max_size = 128; + char output[max_size]; + std::string u; + + if (unit_ == Unit::HOUR) + u = ""; + else + u = unit_.to_string(); + + int err = snprintf(output, max_size, (format + "%s").c_str(), value(), u.c_str()); + if (err < 0 || err >= max_size) { + throw std::runtime_error("Error while formatting Step to string"); } - return ss.str(); + return output; } private: diff --git a/tests/grib_ecc-1212.sh b/tests/grib_ecc-1212.sh index 7ae426756..286e9c0de 100755 --- a/tests/grib_ecc-1212.sh +++ b/tests/grib_ecc-1212.sh @@ -59,6 +59,7 @@ cat > $tempRef < $tempRef << EOF "class": "od", "type": "an", "stream": "oper", + "stepUnits": "h", "step": 0, "levelist": 1000, "levtype": "pl", @@ -58,6 +59,7 @@ cat > $tempRef << EOF "class": "od", "type": "pf", "stream": "enfo", + "stepUnits": "h", "step": 0, "levelist": 1000, "levtype": "pl", diff --git a/tools/grib_options.cc b/tools/grib_options.cc index 0d77dc67d..2ed00ebb1 100644 --- a/tools/grib_options.cc +++ b/tools/grib_options.cc @@ -232,7 +232,7 @@ int grib_process_runtime_options(grib_context* context, int argc, char** argv, g if (grib_options_on("F:")) options->format = grib_options_get_option("F:"); else - options->format = strdup("%g"); + options->format = NULL; if (grib_options_on("i:")) { options->index_on = 1; diff --git a/tools/grib_tools.cc b/tools/grib_tools.cc index 7b008ad3f..7ac2c2256 100644 --- a/tools/grib_tools.cc +++ b/tools/grib_tools.cc @@ -363,6 +363,7 @@ static int grib_tool_without_orderby(grib_runtime_options* options) while (!options->skip_all && ((h = grib_handle_new_from_file_x(c, infile->file, options->mode, options->headers_only, &err)) != NULL || err != GRIB_SUCCESS)) { + infile->handle_count++; options->handle_count++; @@ -412,6 +413,19 @@ static int grib_tool_without_orderby(grib_runtime_options* options) grib_set_string(h, "stepOutputFormat", options->step_output_format, &step_output_format_size); } + if (options->format != NULL) { + size_t format_len = strlen(options->format); + if ((err = grib_set_string_internal(h, "format", options->format, &format_len)) != GRIB_SUCCESS) + return err; + } + else { + char format[1024]; + size_t format_len = sizeof(format); + if ((err = grib_get_string_internal(h, "format", format, &format_len)) != GRIB_SUCCESS) + return err; + options->format = strdup(format); + } + grib_tool_new_handle_action(options, h); grib_print_key_values(options, h); @@ -1201,18 +1215,7 @@ void grib_print_key_values(grib_runtime_options* options, grib_handle* h) break; case GRIB_TYPE_LONG: ret = grib_get_long(h, options->print_keys[i].name, &lvalue); - //if ( - // (strcmp(options->print_keys[i].name, "indicatorOfUnitOfTimeRange") == 0) || - // (strcmp(options->print_keys[i].name, "indicatorOfUnitForTimeRange") == 0) && - // (strcmp(options->step_output_format, "future") == 0) - //) - //{ - // snprintf(value, 32, "%s", StepUnitsTable::to_str(lvalue).c_str()); - //} - //else - //{ - snprintf(value, 32, "%ld", lvalue); - //} + snprintf(value, 32, "%ld", lvalue); break; case GRIB_TYPE_BYTES: ret = grib_get_string(h, options->print_keys[i].name, value, &len); From b842df4fdfb6be8d0ed8333e56c37128679db2a2 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 20 Sep 2023 14:55:57 +0000 Subject: [PATCH 043/125] ECC-1620: Separate step value and step unit --- src/CMakeLists.txt | 1 + src/step.cc | 30 ---------- src/step.h | 142 +------------------------------------------ src/step_unit.cc | 29 +++++++++ src/step_unit.h | 146 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+), 171 deletions(-) create mode 100644 src/step_unit.cc create mode 100644 src/step_unit.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8868d07fe..be8196605 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ # list( APPEND eccodes_src_files step.cc + step_unit.cc step_utilities.cc grib_api.h grib_timer.cc diff --git a/src/step.cc b/src/step.cc index f4f710561..3bb34cc00 100644 --- a/src/step.cc +++ b/src/step.cc @@ -10,34 +10,6 @@ #include "step.h" -UnitType::Map UnitType::map_{}; - - -std::vector UnitType::unit_order_ = { - Unit::SECOND, - Unit::MINUTE, - Unit::HOUR, - //Unit::DAY, -}; - -std::vector UnitType::complete_unit_order_ = { - Unit::MISSING , - Unit::SECOND , - Unit::MINUTE , - Unit::MINUTES15 , - Unit::MINUTES30 , - Unit::HOUR , - Unit::HOURS3 , - Unit::HOURS6 , - Unit::HOURS12 , - Unit::DAY , - Unit::MONTH , - Unit::YEAR , - Unit::YEARS10 , - Unit::YEARS30 , - Unit::CENTURY -}; - Step step_from_string(std::string step) { @@ -170,7 +142,6 @@ void Step::init_long(long value, const UnitType& unit) internal_value_ = value; internal_unit_ = unit; unit_ = internal_unit_; - //unit_.hide_hour_unit(); sanity_check(); } @@ -179,7 +150,6 @@ void Step::init_double(double value, const UnitType& unit) long seconds = UnitType::get_converter().unit_to_duration(unit.to_value()); init_long(static_cast(value * seconds), UnitType{Unit::SECOND}); unit_ = unit; - //unit_.hide_hour_unit(); } Step& Step::optimize_unit() diff --git a/src/step.h b/src/step.h index ed5d9b69c..001239a66 100644 --- a/src/step.h +++ b/src/step.h @@ -5,155 +5,15 @@ #include #include #include -#include #include #include -#include #include #include #include #include #include - -template using Minutes = std::chrono::duration>; -template using Hours = std::chrono::duration>; -template using Days = std::chrono::duration>; -template using Months = std::chrono::duration>; -template using Years = std::chrono::duration>; -template using Years10 = std::chrono::duration>; -template using Years30 = std::chrono::duration>; -template using Centuries = std::chrono::duration>; -template using Hours3 = std::chrono::duration>; -template using Hours6 = std::chrono::duration>; -template using Hours12 = std::chrono::duration>; -template using Seconds = std::chrono::duration>; -template using Minutes15 = std::chrono::duration>; -template using Minutes30 = std::chrono::duration>; -template using Missing = std::chrono::duration>; - -enum class Unit { - MINUTE = 0, - HOUR = 1, - DAY = 2, - MONTH = 3, - YEAR = 4, - YEARS10 = 5, - YEARS30 = 6, - CENTURY = 7, - HOURS3 = 10, - HOURS6 = 11, - HOURS12 = 12, - SECOND = 13, - MINUTES15 = 14, - MINUTES30 = 15, - MISSING = 255, -}; - -class UnitType; -template Seconds to_seconds(long value, const UnitType& unit); -template T from_seconds(Seconds seconds, const UnitType& unit); - -class UnitType { -public: - 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);} - - UnitType& operator=(const Unit value) { - internal_value_ = value; - return *this; - } - - std::string to_string() const { - return map_.unit_to_name(internal_value_); - } - - long to_long() const {return map_.unit_to_long(internal_value_);} - Unit to_value() const {return internal_value_;} - static std::vector unit_order_; - static std::vector complete_unit_order_; - -private: - class Map { - public: - Map() { - for (const auto& entry : tab_) { - // unit_value <-> unit_name - name_to_value_[entry.unit_name] = entry.unit_value; - value_to_name_[entry.unit_value] = entry.unit_name; - - // unit_value <-> duration in seconds - value_to_duration_[entry.unit_value] = entry.duration; - duration_to_value_[entry.duration] = entry.unit_value; - - // unit_value <-> wmo_code - value_to_long_[entry.unit_value] = static_cast(entry.unit_value); - long_to_value_[static_cast(entry.unit_value)] = entry.unit_value; - } - } - - // wmo_code <-> unit_name - std::string unit_to_name(const Unit& unit_value) const {return value_to_name_.at(unit_value);} - Unit name_to_unit(const std::string& name) const {return name_to_value_.at(name);} - - // unit_value <-> duration - long unit_to_duration(const Unit& unit_value) const {return value_to_duration_.at(unit_value);} - Unit duration_to_unit(long duration) const {return duration_to_value_.at(duration);} - - // wmo_code <-> unit_name - long unit_to_long(const Unit& unit_value) const {return value_to_long_.at(unit_value);} - Unit long_to_unit(long wmo_code) const {return long_to_value_.at(wmo_code);} - - private: - struct Entry { - Unit unit_value; - std::string unit_name; - long duration; - }; - - const std::array tab_ = { - Entry{Unit::MISSING , "MISSING" , 0}, - Entry{Unit::SECOND , "s" , 1}, - Entry{Unit::MINUTE , "m" , 60}, - Entry{Unit::MINUTES15 , "15m" , 900}, - Entry{Unit::MINUTES30 , "30m" , 1800}, - Entry{Unit::HOUR , "h" , 3600}, - Entry{Unit::HOURS3 , "3h" , 10800}, - Entry{Unit::HOURS6 , "6h" , 21600}, - Entry{Unit::HOURS12 , "12h" , 43200}, - Entry{Unit::DAY , "D" , 86400}, - Entry{Unit::MONTH , "M" , 2592000}, - Entry{Unit::YEAR , "Y" , 31536000}, - Entry{Unit::YEARS10 , "10Y" , 315360000}, - Entry{Unit::YEARS30 , "30Y" , 946080000}, - Entry{Unit::CENTURY , "C" , 3153600000}, - }; - - std::unordered_map name_to_value_; - std::unordered_map value_to_name_; - - std::unordered_map value_to_long_; - std::unordered_map long_to_value_; - - std::unordered_map value_to_duration_; - std::unordered_map duration_to_value_; - }; - - - Unit internal_value_; - static Map map_; -public: - static Map& get_converter() {return map_;} -}; - +#include "step_unit.h" class Step { public: diff --git a/src/step_unit.cc b/src/step_unit.cc new file mode 100644 index 000000000..2dd4c0812 --- /dev/null +++ b/src/step_unit.cc @@ -0,0 +1,29 @@ +#include "step_unit.h" + +UnitType::Map UnitType::map_{}; + +std::vector UnitType::unit_order_ = { + Unit::SECOND, + Unit::MINUTE, + Unit::HOUR, + //Unit::DAY, +}; + +std::vector UnitType::complete_unit_order_ = { + Unit::MISSING , + Unit::SECOND , + Unit::MINUTE , + Unit::MINUTES15 , + Unit::MINUTES30 , + Unit::HOUR , + Unit::HOURS3 , + Unit::HOURS6 , + Unit::HOURS12 , + Unit::DAY , + Unit::MONTH , + Unit::YEAR , + Unit::YEARS10 , + Unit::YEARS30 , + Unit::CENTURY +}; + diff --git a/src/step_unit.h b/src/step_unit.h new file mode 100644 index 000000000..587ae2898 --- /dev/null +++ b/src/step_unit.h @@ -0,0 +1,146 @@ +#pragma once + +#include +#include +#include +#include +#include + +template using Minutes = std::chrono::duration>; +template using Hours = std::chrono::duration>; +template using Days = std::chrono::duration>; +template using Months = std::chrono::duration>; +template using Years = std::chrono::duration>; +template using Years10 = std::chrono::duration>; +template using Years30 = std::chrono::duration>; +template using Centuries = std::chrono::duration>; +template using Hours3 = std::chrono::duration>; +template using Hours6 = std::chrono::duration>; +template using Hours12 = std::chrono::duration>; +template using Seconds = std::chrono::duration>; +template using Minutes15 = std::chrono::duration>; +template using Minutes30 = std::chrono::duration>; +template using Missing = std::chrono::duration>; + + +enum class Unit { + MINUTE = 0, + HOUR = 1, + DAY = 2, + MONTH = 3, + YEAR = 4, + YEARS10 = 5, + YEARS30 = 6, + CENTURY = 7, + HOURS3 = 10, + HOURS6 = 11, + HOURS12 = 12, + SECOND = 13, + MINUTES15 = 14, + MINUTES30 = 15, + MISSING = 255, +}; + +class UnitType; +template Seconds to_seconds(long value, const UnitType& unit); +template T from_seconds(Seconds seconds, const UnitType& unit); + +class UnitType { +public: + 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);} + + UnitType& operator=(const Unit value) { + internal_value_ = value; + return *this; + } + + std::string to_string() const { + return map_.unit_to_name(internal_value_); + } + + long to_long() const {return map_.unit_to_long(internal_value_);} + Unit to_value() const {return internal_value_;} + static std::vector unit_order_; + static std::vector complete_unit_order_; + +private: + class Map { + public: + Map() { + for (const auto& entry : tab_) { + // unit_value <-> unit_name + name_to_value_[entry.unit_name] = entry.unit_value; + value_to_name_[entry.unit_value] = entry.unit_name; + + // unit_value <-> duration in seconds + value_to_duration_[entry.unit_value] = entry.duration; + duration_to_value_[entry.duration] = entry.unit_value; + + // unit_value <-> wmo_code + value_to_long_[entry.unit_value] = static_cast(entry.unit_value); + long_to_value_[static_cast(entry.unit_value)] = entry.unit_value; + } + } + + // wmo_code <-> unit_name + std::string unit_to_name(const Unit& unit_value) const {return value_to_name_.at(unit_value);} + Unit name_to_unit(const std::string& name) const {return name_to_value_.at(name);} + + // unit_value <-> duration + long unit_to_duration(const Unit& unit_value) const {return value_to_duration_.at(unit_value);} + Unit duration_to_unit(long duration) const {return duration_to_value_.at(duration);} + + // wmo_code <-> unit_name + long unit_to_long(const Unit& unit_value) const {return value_to_long_.at(unit_value);} + Unit long_to_unit(long wmo_code) const {return long_to_value_.at(wmo_code);} + + private: + struct Entry { + Unit unit_value; + std::string unit_name; + long duration; + }; + + const std::array tab_ = { + Entry{Unit::MISSING , "MISSING" , 0}, + Entry{Unit::SECOND , "s" , 1}, + Entry{Unit::MINUTE , "m" , 60}, + Entry{Unit::MINUTES15 , "15m" , 900}, + Entry{Unit::MINUTES30 , "30m" , 1800}, + Entry{Unit::HOUR , "h" , 3600}, + Entry{Unit::HOURS3 , "3h" , 10800}, + Entry{Unit::HOURS6 , "6h" , 21600}, + Entry{Unit::HOURS12 , "12h" , 43200}, + Entry{Unit::DAY , "D" , 86400}, + Entry{Unit::MONTH , "M" , 2592000}, + Entry{Unit::YEAR , "Y" , 31536000}, + Entry{Unit::YEARS10 , "10Y" , 315360000}, + Entry{Unit::YEARS30 , "30Y" , 946080000}, + Entry{Unit::CENTURY , "C" , 3153600000}, + }; + + std::unordered_map name_to_value_; + std::unordered_map value_to_name_; + + std::unordered_map value_to_long_; + std::unordered_map long_to_value_; + + std::unordered_map value_to_duration_; + std::unordered_map duration_to_value_; + }; + + + Unit internal_value_; + static Map map_; +public: + static Map& get_converter() {return map_;} +}; From 0a1b650ba268337f16211251751db5244644a4bf Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 20 Sep 2023 15:07:20 +0000 Subject: [PATCH 044/125] ECC-1620: Refactoring of unit --- src/grib_accessor_class_g2end_step.cc | 10 +- src/grib_accessor_class_optimal_step_units.cc | 11 +- src/grib_accessor_class_step_in_units.cc | 10 +- src/step.cc | 20 +-- src/step.h | 104 +++++++------- src/step_unit.cc | 44 +++--- src/step_unit.h | 127 +++++++++--------- 7 files changed, 163 insertions(+), 163 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index b5e814172..4e04e3714 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -355,10 +355,10 @@ static int unpack_one_time_range_double_(grib_accessor* a, double *val , size_t* } } if (add_time_range) { - *val = (start_step + time_range).value(UnitType(step_units)); + *val = (start_step + time_range).value(Unit(step_units)); } else { - *val = start_step.value(UnitType(start_step_unit)); + *val = start_step.value(Unit(start_step_unit)); } return GRIB_SUCCESS; @@ -470,7 +470,7 @@ static int unpack_multiple_time_ranges_double_(grib_accessor* a, double* val, si long the_coded_time_range = arr_coded_time_range[i]; Step time_range{the_coded_unit, the_coded_time_range}; - *val = (start_step + time_range).value(UnitType(step_units)); + *val = (start_step + time_range).value(Unit(step_units)); return GRIB_SUCCESS; } @@ -633,7 +633,7 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if (err != GRIB_SUCCESS) return err; - dstep = end_step.value(UnitType{Unit::DAY}); + dstep = end_step.value(Unit{Unit::Value::DAY}); dend += dstep; err = grib_julian_to_datetime(dend, &year_of_end_of_interval, &month_of_end_of_interval, @@ -765,7 +765,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return ret; if (end_step_unit == 255) - end_step_unit = UnitType{Unit::HOUR}.to_long(); + end_step_unit = Unit{Unit::Value::HOUR}.to_long(); } else { end_step_unit = force_step_units; diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 9a828e8d6..f09b61f38 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -142,8 +142,8 @@ static size_t string_length(grib_accessor* a) return 255; } -static long staticStepUnits = UnitType{Unit::MISSING}.to_long(); -static long staticForceStepUnits = UnitType{Unit::MISSING}.to_long(); +static long staticStepUnits = Unit{Unit::Value::MISSING}.to_long(); +static long staticForceStepUnits = Unit{Unit::Value::MISSING}.to_long(); static int pack_long(grib_accessor* a, const long* val, size_t* len) { @@ -183,7 +183,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) *val = time_range_opt.value().optimize_unit().unit().to_long(); } else if (!forecast_time_opt && !time_range_opt) { - *val = UnitType{Unit::HOUR}.to_long(); + *val = Unit{Unit::Value::HOUR}.to_long(); } return GRIB_SUCCESS; @@ -191,7 +191,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { - long unit = UnitType{val}.to_long(); + long unit = Unit{val}.to_long(); pack_long(a, &unit, len); return GRIB_SUCCESS; } @@ -203,11 +203,10 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) size_t unit_len = 0; if ((ret = unpack_long(a, &unit, &unit_len)) != GRIB_SUCCESS) return ret; - *len = snprintf(val, *len, "%s", UnitType{unit}.to_string().c_str()); + *len = snprintf(val, *len, "%s", Unit{unit}.to_string().c_str()); return GRIB_SUCCESS; } - static int get_native_type(grib_accessor* a) { return GRIB_TYPE_LONG; diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 74f2cce34..1de9d5540 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -192,10 +192,10 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) Step step{forecast_time_value, forecast_time_unit}; - if ((err = grib_set_long_internal(h, "startStepUnit", UnitType{step_units}.to_long())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.to_long())) != GRIB_SUCCESS) return err; - *val = step.value(UnitType{step_units}); + *val = step.value(Unit{step_units}); return GRIB_SUCCESS; } @@ -220,10 +220,10 @@ static int unpack_double(grib_accessor* a, double * val, size_t* len) Step step{forecast_time_value, forecast_time_unit}; - if ((err = grib_set_long_internal(h, "startStepUnit", UnitType{step_units}.to_long())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.to_long())) != GRIB_SUCCESS) return err; - *val = step.value(UnitType{step_units}); + *val = step.value(Unit{step_units}); return GRIB_SUCCESS; } @@ -349,7 +349,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return ret; if (start_step_unit == 255) - start_step_unit = UnitType{Unit::HOUR}.to_long(); + start_step_unit = Unit{Unit::Value::HOUR}.to_long(); } else { start_step_unit = force_step_units; diff --git a/src/step.cc b/src/step.cc index 3bb34cc00..a61bc6dfa 100644 --- a/src/step.cc +++ b/src/step.cc @@ -22,7 +22,7 @@ Step step_from_string(std::string step) if (unit.size() == 0) { unit = "h"; } - Step ret{std::stod(value), UnitType{unit}}; + Step ret{std::stod(value), Unit{unit}}; return ret; } } @@ -93,7 +93,7 @@ std::pair find_common_units(const Step& startStep, const Step& endSt 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_; + Unit unit = a.internal_unit_ > b.internal_unit_ ? a.internal_unit_ : b.internal_unit_; b.internal_unit_ = unit; b.unit_ = unit; a.internal_unit_ = unit; @@ -112,11 +112,11 @@ std::pair find_common_units(const Step& startStep, const Step& endSt b.recalculateValue(); } else { - auto it = std::find_if(UnitType::unit_order_.begin(), UnitType::unit_order_.end(), [&](const auto& e) { + auto it = std::find_if(Unit::unit_order_.begin(), Unit::unit_order_.end(), [&](const auto& e) { return e == a.unit().to_value() || e == b.unit().to_value(); }); - assert(it != UnitType::unit_order_.end()); + assert(it != Unit::unit_order_.end()); a.set_unit(*it); b.set_unit(*it); @@ -137,7 +137,7 @@ void Step::sanity_check() const } -void Step::init_long(long value, const UnitType& unit) +void Step::init_long(long value, const Unit& unit) { internal_value_ = value; internal_unit_ = unit; @@ -145,10 +145,10 @@ void Step::init_long(long value, const UnitType& unit) sanity_check(); } -void Step::init_double(double value, const UnitType& unit) +void Step::init_double(double value, const Unit& unit) { - long seconds = UnitType::get_converter().unit_to_duration(unit.to_value()); - init_long(static_cast(value * seconds), UnitType{Unit::SECOND}); + long seconds = Unit::get_converter().unit_to_duration(unit.to_value()); + init_long(static_cast(value * seconds), Unit{Unit::Value::SECOND}); unit_ = unit; } @@ -161,8 +161,8 @@ Step& Step::optimize_unit() unit_ = internal_unit_; Seconds seconds = to_seconds(internal_value_, internal_unit_); - for (auto it = UnitType::unit_order_.rbegin(); it != UnitType::unit_order_.rend(); ++it) { - long multiplier = UnitType::get_converter().unit_to_duration(*it); + for (auto it = Unit::unit_order_.rbegin(); it != Unit::unit_order_.rend(); ++it) { + long multiplier = Unit::get_converter().unit_to_duration(*it); if (seconds.count() % multiplier == 0) { internal_value_ = seconds.count() / multiplier; internal_unit_ = *it; diff --git a/src/step.h b/src/step.h index 001239a66..261d9edb8 100644 --- a/src/step.h +++ b/src/step.h @@ -18,28 +18,28 @@ class Step { public: // Constructors - Step() : internal_value_(0), internal_unit_(Unit::SECOND) {} + Step() : internal_value_(0), internal_unit_(Unit::Value::SECOND) {} - Step(double value, const UnitType& unit) : internal_unit_{unit}, unit_{internal_unit_} {init_double(value, unit);} - Step(double value, Unit unit) {init_double(value, UnitType{unit});} - Step(double value, long unit) {init_double(value, UnitType{unit});} - Step(double value, const std::string& unit) {init_double(value, UnitType{unit});} + Step(double value, const Unit& unit) : internal_unit_{unit}, unit_{internal_unit_} {init_double(value, unit);} + Step(double value, Unit::Value unit) {init_double(value, Unit{unit});} + Step(double value, long unit) {init_double(value, Unit{unit});} + Step(double value, const std::string& unit) {init_double(value, Unit{unit});} - Step(long value, const UnitType& unit) { init_long(value, unit);} - Step(long value, Unit unit) {init_long(value, UnitType{unit});} - Step(long value, long unit) {init_long(value, UnitType{unit});} - Step(long value, const std::string& unit) {init_long(value, UnitType{unit});} + Step(long value, const Unit& unit) { init_long(value, unit);} + Step(long value, Unit::Value unit) {init_long(value, Unit{unit});} + Step(long value, long unit) {init_long(value, Unit{unit});} + Step(long value, const std::string& unit) {init_long(value, Unit{unit});} // Getters template T value() const; - template T value(const UnitType& unit) const; - UnitType unit() const { return unit_; } + template T value(const Unit& unit) const; + Unit unit() const { return unit_; } // Setters - Step& set_unit(const std::string& unit_name) {unit_ = UnitType{unit_name}; return *this;} - Step& set_unit(long unit_code) {unit_ = UnitType{unit_code}; return *this;} - Step& set_unit(const UnitType& new_unit) {unit_ = new_unit; return *this;} - Step& set_unit(const Unit new_unit) {unit_ = new_unit; return *this;} + Step& set_unit(const std::string& unit_name) {unit_ = Unit{unit_name}; return *this;} + Step& set_unit(long unit_code) {unit_ = Unit{unit_code}; return *this;} + Step& set_unit(const Unit& new_unit) {unit_ = new_unit; return *this;} + Step& set_unit(const Unit::Value new_unit) {unit_ = new_unit; return *this;} // Operators bool operator==(const Step& other) const; @@ -65,7 +65,7 @@ public: char output[max_size]; std::string u; - if (unit_ == Unit::HOUR) + if (unit_ == Unit::Value::HOUR) u = ""; else u = unit_.to_string(); @@ -78,8 +78,8 @@ public: } private: - void init_long(long value, const UnitType& unit); - void init_double(double value, const UnitType& unit); + void init_long(long value, const Unit& unit); + void init_double(double value, const Unit& unit); void sanity_check() const; Step& recalculateValue() { if (internal_value_ == 0) { @@ -88,7 +88,7 @@ private: } Seconds seconds = to_seconds(internal_value_, internal_unit_); - long multiplier = UnitType::get_converter().unit_to_duration(unit_.to_value()); + long multiplier = Unit::get_converter().unit_to_duration(unit_.to_value()); internal_value_ = seconds.count() / multiplier; internal_unit_ = unit_; @@ -96,8 +96,8 @@ private: } long internal_value_; - UnitType internal_unit_; - UnitType unit_; + Unit internal_unit_; + Unit unit_; }; @@ -118,7 +118,7 @@ template T Step::value() const { return value; } -template T Step::value(const UnitType& unit) const { +template T Step::value(const Unit& unit) const { if (internal_value_ == 0) { return 0; } @@ -132,23 +132,23 @@ template T Step::value(const UnitType& unit) const { template -Seconds to_seconds(long value, const UnitType& unit) { +Seconds to_seconds(long value, const Unit& unit) { Seconds seconds; switch (unit.to_value()) { - case Unit::SECOND: seconds = Seconds(value); break; - case Unit::MINUTE: seconds = Minutes(value); break; - case Unit::MINUTES15: seconds = Minutes15(value); break; - case Unit::MINUTES30: seconds = Minutes30(value); break; - case Unit::HOUR: seconds = Hours(value); break; - case Unit::HOURS3: seconds = Hours3(value); break; - case Unit::HOURS6: seconds = Hours6(value); break; - case Unit::HOURS12: seconds = Hours12(value); break; - case Unit::DAY: seconds = Days(value); break; - case Unit::MONTH: seconds = Months(value); break; - case Unit::YEAR: seconds = Years(value); break; - case Unit::YEARS10: seconds = Years10(value); break; - case Unit::YEARS30: seconds = Years30(value); break; - case Unit::CENTURY: seconds = Centuries(value); break; + case Unit::Value::SECOND: seconds = Seconds(value); break; + case Unit::Value::MINUTE: seconds = Minutes(value); break; + case Unit::Value::MINUTES15: seconds = Minutes15(value); break; + case Unit::Value::MINUTES30: seconds = Minutes30(value); break; + case Unit::Value::HOUR: seconds = Hours(value); break; + case Unit::Value::HOURS3: seconds = Hours3(value); break; + case Unit::Value::HOURS6: seconds = Hours6(value); break; + case Unit::Value::HOURS12: seconds = Hours12(value); break; + case Unit::Value::DAY: seconds = Days(value); break; + case Unit::Value::MONTH: seconds = Months(value); break; + case Unit::Value::YEAR: seconds = Years(value); break; + case Unit::Value::YEARS10: seconds = Years10(value); break; + case Unit::Value::YEARS30: seconds = Years30(value); break; + case Unit::Value::CENTURY: seconds = Centuries(value); break; default: std::string msg = "Unknown unit: " + unit.to_string(); throw std::runtime_error(msg); @@ -158,23 +158,23 @@ Seconds to_seconds(long value, const UnitType& unit) { template -T from_seconds(Seconds seconds, const UnitType& unit) { +T from_seconds(Seconds seconds, const Unit& unit) { T value = 0; switch (unit.to_value()) { - case Unit::SECOND: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::MINUTE: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::MINUTES15: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::MINUTES30: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::HOUR: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::HOURS3: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::HOURS6: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::HOURS12: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::DAY: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::MONTH: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::YEAR: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::YEARS10: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::YEARS30: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::CENTURY: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::SECOND: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::MINUTE: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::MINUTES15: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::MINUTES30: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::HOUR: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::HOURS3: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::HOURS6: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::HOURS12: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::DAY: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::MONTH: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::YEAR: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::YEARS10: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::YEARS30: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::CENTURY: value = std::chrono::duration_cast>(seconds).count(); break; default: std::string msg = "Unknown unit: " + unit.to_string(); throw std::runtime_error(msg); diff --git a/src/step_unit.cc b/src/step_unit.cc index 2dd4c0812..e24e3a0d5 100644 --- a/src/step_unit.cc +++ b/src/step_unit.cc @@ -1,29 +1,29 @@ #include "step_unit.h" -UnitType::Map UnitType::map_{}; +Unit::Map Unit::map_{}; -std::vector UnitType::unit_order_ = { - Unit::SECOND, - Unit::MINUTE, - Unit::HOUR, - //Unit::DAY, +std::vector Unit::unit_order_ = { + Unit::Value::SECOND, + Unit::Value::MINUTE, + Unit::Value::HOUR, + //Unit::Value::DAY, }; -std::vector UnitType::complete_unit_order_ = { - Unit::MISSING , - Unit::SECOND , - Unit::MINUTE , - Unit::MINUTES15 , - Unit::MINUTES30 , - Unit::HOUR , - Unit::HOURS3 , - Unit::HOURS6 , - Unit::HOURS12 , - Unit::DAY , - Unit::MONTH , - Unit::YEAR , - Unit::YEARS10 , - Unit::YEARS30 , - Unit::CENTURY +std::vector Unit::complete_unit_order_ = { + Unit::Value::MISSING , + Unit::Value::SECOND , + Unit::Value::MINUTE , + Unit::Value::MINUTES15 , + Unit::Value::MINUTES30 , + Unit::Value::HOUR , + Unit::Value::HOURS3 , + Unit::Value::HOURS6 , + Unit::Value::HOURS12 , + Unit::Value::DAY , + Unit::Value::MONTH , + Unit::Value::YEAR , + Unit::Value::YEARS10 , + Unit::Value::YEARS30 , + Unit::Value::CENTURY }; diff --git a/src/step_unit.h b/src/step_unit.h index 587ae2898..2fc3fe934 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -23,42 +23,43 @@ template using Minutes30 = std::chrono::duration using Missing = std::chrono::duration>; -enum class Unit { - MINUTE = 0, - HOUR = 1, - DAY = 2, - MONTH = 3, - YEAR = 4, - YEARS10 = 5, - YEARS30 = 6, - CENTURY = 7, - HOURS3 = 10, - HOURS6 = 11, - HOURS12 = 12, - SECOND = 13, - MINUTES15 = 14, - MINUTES30 = 15, - MISSING = 255, -}; -class UnitType; -template Seconds to_seconds(long value, const UnitType& unit); -template T from_seconds(Seconds seconds, const UnitType& unit); +class Unit; +template Seconds to_seconds(long value, const Unit& unit); +template T from_seconds(Seconds seconds, const Unit& unit); -class UnitType { +class Unit { public: - 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);} + enum class Value { + MINUTE = 0, + HOUR = 1, + DAY = 2, + MONTH = 3, + YEAR = 4, + YEARS10 = 5, + YEARS30 = 6, + CENTURY = 7, + HOURS3 = 10, + HOURS6 = 11, + HOURS12 = 12, + SECOND = 13, + MINUTES15 = 14, + MINUTES30 = 15, + MISSING = 255, + }; - 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);} + Unit() : internal_value_(Value::HOUR) {} + explicit Unit(Value unit_value) : internal_value_(unit_value) {} + explicit Unit(const std::string& unit_value) {internal_value_ = map_.name_to_unit(unit_value);} + explicit Unit(long unit_value) {internal_value_ = map_.long_to_unit(unit_value);} - UnitType& operator=(const Unit value) { + bool operator>(const Unit& other) const {return map_.unit_to_duration(internal_value_) > map_.unit_to_duration(other.internal_value_);} + bool operator==(const Value value) const {return map_.unit_to_duration(internal_value_) == map_.unit_to_duration(value);} + bool operator==(const Unit& unit) const {return map_.unit_to_duration(internal_value_) == map_.unit_to_duration(unit.internal_value_);} + bool operator!=(const Unit& unit) const {return !(*this == unit);} + bool operator!=(const Value value) const {return !(*this == value);} + + Unit& operator=(const Value value) { internal_value_ = value; return *this; } @@ -68,9 +69,9 @@ public: } long to_long() const {return map_.unit_to_long(internal_value_);} - Unit to_value() const {return internal_value_;} - static std::vector unit_order_; - static std::vector complete_unit_order_; + Value to_value() const {return internal_value_;} + static std::vector unit_order_; + static std::vector complete_unit_order_; private: class Map { @@ -92,54 +93,54 @@ private: } // wmo_code <-> unit_name - std::string unit_to_name(const Unit& unit_value) const {return value_to_name_.at(unit_value);} - Unit name_to_unit(const std::string& name) const {return name_to_value_.at(name);} + std::string unit_to_name(const Value& unit_value) const {return value_to_name_.at(unit_value);} + Value name_to_unit(const std::string& name) const {return name_to_value_.at(name);} // unit_value <-> duration - long unit_to_duration(const Unit& unit_value) const {return value_to_duration_.at(unit_value);} - Unit duration_to_unit(long duration) const {return duration_to_value_.at(duration);} + long unit_to_duration(const Value& unit_value) const {return value_to_duration_.at(unit_value);} + Value duration_to_unit(long duration) const {return duration_to_value_.at(duration);} // wmo_code <-> unit_name - long unit_to_long(const Unit& unit_value) const {return value_to_long_.at(unit_value);} - Unit long_to_unit(long wmo_code) const {return long_to_value_.at(wmo_code);} + long unit_to_long(const Value& unit_value) const {return value_to_long_.at(unit_value);} + Value long_to_unit(long wmo_code) const {return long_to_value_.at(wmo_code);} private: struct Entry { - Unit unit_value; + Value unit_value; std::string unit_name; long duration; }; const std::array tab_ = { - Entry{Unit::MISSING , "MISSING" , 0}, - Entry{Unit::SECOND , "s" , 1}, - Entry{Unit::MINUTE , "m" , 60}, - Entry{Unit::MINUTES15 , "15m" , 900}, - Entry{Unit::MINUTES30 , "30m" , 1800}, - Entry{Unit::HOUR , "h" , 3600}, - Entry{Unit::HOURS3 , "3h" , 10800}, - Entry{Unit::HOURS6 , "6h" , 21600}, - Entry{Unit::HOURS12 , "12h" , 43200}, - Entry{Unit::DAY , "D" , 86400}, - Entry{Unit::MONTH , "M" , 2592000}, - Entry{Unit::YEAR , "Y" , 31536000}, - Entry{Unit::YEARS10 , "10Y" , 315360000}, - Entry{Unit::YEARS30 , "30Y" , 946080000}, - Entry{Unit::CENTURY , "C" , 3153600000}, + Entry{Value::MISSING , "MISSING" , 0}, + Entry{Value::SECOND , "s" , 1}, + Entry{Value::MINUTE , "m" , 60}, + Entry{Value::MINUTES15 , "15m" , 900}, + Entry{Value::MINUTES30 , "30m" , 1800}, + Entry{Value::HOUR , "h" , 3600}, + Entry{Value::HOURS3 , "3h" , 10800}, + Entry{Value::HOURS6 , "6h" , 21600}, + Entry{Value::HOURS12 , "12h" , 43200}, + Entry{Value::DAY , "D" , 86400}, + Entry{Value::MONTH , "M" , 2592000}, + Entry{Value::YEAR , "Y" , 31536000}, + Entry{Value::YEARS10 , "10Y" , 315360000}, + Entry{Value::YEARS30 , "30Y" , 946080000}, + Entry{Value::CENTURY , "C" , 3153600000}, }; - std::unordered_map name_to_value_; - std::unordered_map value_to_name_; + std::unordered_map name_to_value_; + std::unordered_map value_to_name_; - std::unordered_map value_to_long_; - std::unordered_map long_to_value_; + std::unordered_map value_to_long_; + std::unordered_map long_to_value_; - std::unordered_map value_to_duration_; - std::unordered_map duration_to_value_; + std::unordered_map value_to_duration_; + std::unordered_map duration_to_value_; }; - Unit internal_value_; + Value internal_value_; static Map map_; public: static Map& get_converter() {return map_;} From 249867cc4a144c963b92caa3c91082ed30139c07 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 20 Sep 2023 15:16:55 +0000 Subject: [PATCH 045/125] ECC-1620: Refactor Unit::value() --- src/grib_accessor_class_g2end_step.cc | 10 +++++----- src/grib_accessor_class_g2step_range.cc | 4 ++-- src/grib_accessor_class_optimal_step_units.cc | 16 ++++++++-------- src/grib_accessor_class_step_in_units.cc | 12 ++++++------ src/step.cc | 4 ++-- src/step.h | 14 +++++++------- src/step_unit.cc | 11 +++++++++++ src/step_unit.h | 12 ++++++------ src/step_utilities.cc | 2 +- 9 files changed, 48 insertions(+), 37 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 4e04e3714..3a9509745 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -690,11 +690,11 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range_opt.value())) != GRIB_SUCCESS) return err; - if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, time_range_opt.unit().to_long())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, time_range_opt.unit().value())) != GRIB_SUCCESS) return err; if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_value_key, forecast_time_opt.value())) != GRIB_SUCCESS) return err; - if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_unit_key, forecast_time_opt.unit().to_long())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_unit_key, forecast_time_opt.unit().value())) != GRIB_SUCCESS) return err; @@ -765,7 +765,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return ret; if (end_step_unit == 255) - end_step_unit = Unit{Unit::Value::HOUR}.to_long(); + end_step_unit = Unit{Unit::Value::HOUR}.value(); } else { end_step_unit = force_step_units; @@ -783,10 +783,10 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) Step end_step = step_from_string(val); end_step.optimize_unit(); - if ((ret = grib_set_long_internal(h, "endStepUnit", end_step.unit().to_long())) != GRIB_SUCCESS) + if ((ret = grib_set_long_internal(h, "endStepUnit", end_step.unit().value())) != GRIB_SUCCESS) return ret; - if ((ret = pack_long_(a, end_step.value(), end_step.unit().to_long())) != GRIB_SUCCESS) + if ((ret = pack_long_(a, end_step.value(), end_step.unit().value())) != GRIB_SUCCESS) return ret; return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 3d4e61228..0578a08e3 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -237,13 +237,13 @@ static int pack_string_new(grib_accessor* a, const char* val, size_t* len) std::tie(step_0, step_1) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); } - if ((ret = grib_set_long_internal(h, "startStepUnit", step_0.unit().to_long()))) + if ((ret = grib_set_long_internal(h, "startStepUnit", step_0.unit().value()))) return ret; if ((ret = set_step(h, "forecastTime" , "indicatorOfUnitOfTimeRange", step_0)) != GRIB_SUCCESS) return ret; if ((self->end_step != NULL) && (steps.size() > 1)) { - if ((ret = grib_set_long_internal(h, "endStepUnit", step_1.unit().to_long()))) + if ((ret = grib_set_long_internal(h, "endStepUnit", step_1.unit().value()))) return ret; if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) return ret; diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index f09b61f38..384c3800e 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -142,8 +142,8 @@ static size_t string_length(grib_accessor* a) return 255; } -static long staticStepUnits = Unit{Unit::Value::MISSING}.to_long(); -static long staticForceStepUnits = Unit{Unit::Value::MISSING}.to_long(); +static long staticStepUnits = Unit{Unit::Value::MISSING}.value(); +static long staticForceStepUnits = Unit{Unit::Value::MISSING}.value(); static int pack_long(grib_accessor* a, const long* val, size_t* len) { @@ -174,16 +174,16 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) if (forecast_time_opt && time_range_opt) { auto [step_a, step_b] = find_common_units(forecast_time_opt.value().optimize_unit(), (forecast_time_opt.value() + time_range_opt.value()).optimize_unit()); - *val = step_a.unit().to_long(); + *val = step_a.unit().value(); } else if (forecast_time_opt && !time_range_opt) { - *val = forecast_time_opt.value().optimize_unit().unit().to_long(); + *val = forecast_time_opt.value().optimize_unit().unit().value(); } else if (!forecast_time_opt && time_range_opt) { - *val = time_range_opt.value().optimize_unit().unit().to_long(); + *val = time_range_opt.value().optimize_unit().unit().value(); } else if (!forecast_time_opt && !time_range_opt) { - *val = Unit{Unit::Value::HOUR}.to_long(); + *val = Unit{Unit::Value::HOUR}.value(); } return GRIB_SUCCESS; @@ -191,7 +191,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { - long unit = Unit{val}.to_long(); + long unit = Unit{val}.value(); pack_long(a, &unit, len); return GRIB_SUCCESS; } @@ -203,7 +203,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) size_t unit_len = 0; if ((ret = unpack_long(a, &unit, &unit_len)) != GRIB_SUCCESS) return ret; - *len = snprintf(val, *len, "%s", Unit{unit}.to_string().c_str()); + *len = snprintf(val, *len, "%s", Unit{unit}.value().c_str()); return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 1de9d5540..f47d9bfd0 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -192,7 +192,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) Step step{forecast_time_value, forecast_time_unit}; - if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.to_long())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.value())) != GRIB_SUCCESS) return err; *val = step.value(Unit{step_units}); @@ -220,7 +220,7 @@ static int unpack_double(grib_accessor* a, double * val, size_t* len) Step step{forecast_time_value, forecast_time_unit}; - if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.to_long())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.value())) != GRIB_SUCCESS) return err; *val = step.value(Unit{step_units}); @@ -318,7 +318,7 @@ int pack_long_new_(grib_accessor* a, const long start_step_value, const long sta auto [sa, sb] = find_common_units(forecast_time.optimize_unit(), time_range.optimize_unit()); if ((err = set_step(h, self->forecast_time_value, self->forecast_time_unit, sa)) != GRIB_SUCCESS) return err; - if ((err = grib_set_long_internal(h, "startStepUnit", forecast_time.unit().to_long())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(h, "startStepUnit", forecast_time.unit().value())) != GRIB_SUCCESS) return err; if ((err = set_step(h, self->time_range_value, self->time_range_unit, sb)) != GRIB_SUCCESS) return err; @@ -326,7 +326,7 @@ int pack_long_new_(grib_accessor* a, const long start_step_value, const long sta } forecast_time.optimize_unit(); - if ((err = grib_set_long_internal(h, "startStepUnit", forecast_time.unit().to_long())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(h, "startStepUnit", forecast_time.unit().value())) != GRIB_SUCCESS) return err; if ((err = set_step(h, self->forecast_time_value, self->forecast_time_unit, forecast_time)) != GRIB_SUCCESS) return err; @@ -349,7 +349,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return ret; if (start_step_unit == 255) - start_step_unit = Unit{Unit::Value::HOUR}.to_long(); + start_step_unit = Unit{Unit::Value::HOUR}.value(); } else { start_step_unit = force_step_units; @@ -369,7 +369,7 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) Step step = step_from_string(val); - if ((ret = pack_long_new_(a, step.value(), step.unit().to_long())) != GRIB_SUCCESS) + if ((ret = pack_long_new_(a, step.value(), step.unit().value())) != GRIB_SUCCESS) return ret; return GRIB_SUCCESS; diff --git a/src/step.cc b/src/step.cc index a61bc6dfa..060a506ef 100644 --- a/src/step.cc +++ b/src/step.cc @@ -113,7 +113,7 @@ std::pair find_common_units(const Step& startStep, const Step& endSt } else { auto it = std::find_if(Unit::unit_order_.begin(), Unit::unit_order_.end(), [&](const auto& e) { - return e == a.unit().to_value() || e == b.unit().to_value(); + return e == a.unit().value() || e == b.unit().value(); }); assert(it != Unit::unit_order_.end()); @@ -147,7 +147,7 @@ void Step::init_long(long value, const Unit& unit) void Step::init_double(double value, const Unit& unit) { - long seconds = Unit::get_converter().unit_to_duration(unit.to_value()); + long seconds = Unit::get_converter().unit_to_duration(unit.value()); init_long(static_cast(value * seconds), Unit{Unit::Value::SECOND}); unit_ = unit; } diff --git a/src/step.h b/src/step.h index 261d9edb8..1c80d380c 100644 --- a/src/step.h +++ b/src/step.h @@ -68,7 +68,7 @@ public: if (unit_ == Unit::Value::HOUR) u = ""; else - u = unit_.to_string(); + u = unit_.value(); int err = snprintf(output, max_size, (format + "%s").c_str(), value(), u.c_str()); if (err < 0 || err >= max_size) { @@ -88,7 +88,7 @@ private: } Seconds seconds = to_seconds(internal_value_, internal_unit_); - long multiplier = Unit::get_converter().unit_to_duration(unit_.to_value()); + long multiplier = Unit::get_converter().unit_to_duration(unit_.value()); internal_value_ = seconds.count() / multiplier; internal_unit_ = unit_; @@ -134,7 +134,7 @@ template T Step::value(const Unit& unit) const { template Seconds to_seconds(long value, const Unit& unit) { Seconds seconds; - switch (unit.to_value()) { + switch (unit.value()) { case Unit::Value::SECOND: seconds = Seconds(value); break; case Unit::Value::MINUTE: seconds = Minutes(value); break; case Unit::Value::MINUTES15: seconds = Minutes15(value); break; @@ -150,7 +150,7 @@ Seconds to_seconds(long value, const Unit& unit) { case Unit::Value::YEARS30: seconds = Years30(value); break; case Unit::Value::CENTURY: seconds = Centuries(value); break; default: - std::string msg = "Unknown unit: " + unit.to_string(); + std::string msg = "Unknown unit: " + unit.value(); throw std::runtime_error(msg); } return seconds; @@ -159,8 +159,8 @@ Seconds to_seconds(long value, const Unit& unit) { template T from_seconds(Seconds seconds, const Unit& unit) { - T value = 0; - switch (unit.to_value()) { + T value; + switch (unit.value()) { case Unit::Value::SECOND: value = std::chrono::duration_cast>(seconds).count(); break; case Unit::Value::MINUTE: value = std::chrono::duration_cast>(seconds).count(); break; case Unit::Value::MINUTES15: value = std::chrono::duration_cast>(seconds).count(); break; @@ -176,7 +176,7 @@ T from_seconds(Seconds seconds, const Unit& unit) { case Unit::Value::YEARS30: value = std::chrono::duration_cast>(seconds).count(); break; case Unit::Value::CENTURY: value = std::chrono::duration_cast>(seconds).count(); break; default: - std::string msg = "Unknown unit: " + unit.to_string(); + std::string msg = "Unknown unit: " + unit.value(); throw std::runtime_error(msg); } return value; diff --git a/src/step_unit.cc b/src/step_unit.cc index e24e3a0d5..3c450fcf2 100644 --- a/src/step_unit.cc +++ b/src/step_unit.cc @@ -27,3 +27,14 @@ std::vector Unit::complete_unit_order_ = { Unit::Value::CENTURY }; +template <> long Unit::value() const { + return map_.unit_to_long(internal_value_); +} + +template <> Unit::Value Unit::value() const { + return internal_value_; +} + +template <> std::string Unit::value() const { + return map_.unit_to_name(internal_value_); +} diff --git a/src/step_unit.h b/src/step_unit.h index 2fc3fe934..1c5c0b196 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -64,12 +64,12 @@ public: return *this; } - std::string to_string() const { - return map_.unit_to_name(internal_value_); - } - - long to_long() const {return map_.unit_to_long(internal_value_);} - Value to_value() const {return internal_value_;} + //std::string to_string() const { + // return map_.unit_to_name(internal_value_); + //} + //long to_long() const {return map_.unit_to_long(internal_value_);} + //Value to_value() const {return internal_value_;} + template T value() const; static std::vector unit_order_; static std::vector complete_unit_order_; diff --git a/src/step_utilities.cc b/src/step_utilities.cc index d46d1900e..cbea1621d 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -28,7 +28,7 @@ int set_step(grib_handle* h, const std::string& value_key, const std::string& un //step_copy.optimize_unit(); if ((err = grib_set_long_internal(h, value_key.c_str(), step_copy.value())) != GRIB_SUCCESS) return err; - if ((err = grib_set_long_internal(h, unit_key.c_str(), step_copy.unit().to_long())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(h, unit_key.c_str(), step_copy.unit().value())) != GRIB_SUCCESS) return err; return GRIB_SUCCESS; } From fe45013440db86d0f387f9d45ee95102a9c368df Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 20 Sep 2023 15:31:57 +0000 Subject: [PATCH 046/125] ECC-1620: Refactoring Step::value() --- src/grib_accessor_class_g2end_step.cc | 4 ++-- src/grib_accessor_class_g2step_range.cc | 6 +++--- src/grib_accessor_class_step_in_units.cc | 2 +- src/step.cc | 20 ++++++++++++++++++++ src/step.h | 17 +---------------- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 3a9509745..cacdfb087 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -625,7 +625,7 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if (time_range.value() < 0) { grib_context_log(h->context, GRIB_LOG_ERROR, - "endStep < startStep (%s < %s)", end_step.to_string("%g").c_str(), start_step.to_string("%g").c_str()); + "endStep < startStep (%s < %s)", end_step.value("%g").c_str(), start_step.value("%g").c_str()); return GRIB_WRONG_STEP; } @@ -735,7 +735,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) std::stringstream ss; - ss << step.to_string(fp_format); + ss << step.value(fp_format); size_t size = ss.str().size() + 1; diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 0578a08e3..7ece162f0 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -163,7 +163,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) Step start_step{start_step_value, step_units}; if (self->end_step == NULL) { - ss << start_step.to_string(fp_format); + ss << start_step.value(fp_format); } else { if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) @@ -172,10 +172,10 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) Step end_step{end_step_value, step_units}; if (start_step_value == end_step_value) { - ss << end_step.to_string(fp_format); + ss << end_step.value(fp_format); } else { - ss << start_step.to_string(fp_format) << "-" << end_step.to_string(fp_format); + ss << start_step.value(fp_format) << "-" << end_step.value(fp_format); } } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index f47d9bfd0..e10a14f39 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -398,7 +398,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) Step step{start_step_value, start_step_unit}; std::stringstream ss; - ss << step.to_string(fp_format); + ss << step.value(fp_format); size_t size = ss.str().size() + 1; diff --git a/src/step.cc b/src/step.cc index 060a506ef..c402c8e2e 100644 --- a/src/step.cc +++ b/src/step.cc @@ -173,3 +173,23 @@ Step& Step::optimize_unit() return *this; } + + +template <> +std::string Step::value(const std::string& format) const { + constexpr int max_size = 128; + char output[max_size]; + std::string u; + + if (unit_ == Unit::Value::HOUR) + u = ""; + else + u = unit_.value(); + + int err = snprintf(output, max_size, (format + "%s").c_str(), value(), u.c_str()); + if (err < 0 || err >= max_size) { + throw std::runtime_error("Error while formatting Step to string"); + } + return output; +} + diff --git a/src/step.h b/src/step.h index 1c80d380c..98996fe08 100644 --- a/src/step.h +++ b/src/step.h @@ -33,6 +33,7 @@ public: // Getters template T value() const; template T value(const Unit& unit) const; + template T value(const std::string& format) const; Unit unit() const { return unit_; } // Setters @@ -60,22 +61,6 @@ public: Step& optimize_unit(); friend std::pair find_common_units(const Step& startStep, const Step& endStep); - std::string to_string(const std::string& format) const { - constexpr int max_size = 128; - char output[max_size]; - std::string u; - - if (unit_ == Unit::Value::HOUR) - u = ""; - else - u = unit_.value(); - - int err = snprintf(output, max_size, (format + "%s").c_str(), value(), u.c_str()); - if (err < 0 || err >= max_size) { - throw std::runtime_error("Error while formatting Step to string"); - } - return output; - } private: void init_long(long value, const Unit& unit); From 624e51513c621e1cabda66c9bd8bf19a01be48b8 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 21 Sep 2023 12:26:02 +0000 Subject: [PATCH 047/125] ECC-1620: Minor changes --- src/CMakeLists.txt | 2 +- src/grib_accessor_class_g2end_step.cc | 111 +++----------------------- src/step.cc | 10 ++- src/step.h | 53 ------------ src/step_unit.h | 59 ++++++++++++-- 5 files changed, 76 insertions(+), 159 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be8196605..31f115f84 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,8 +9,8 @@ # nor does it submit to any jurisdiction. # list( APPEND eccodes_src_files - step.cc step_unit.cc + step.cc step_utilities.cc grib_api.h grib_timer.cc diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index cacdfb087..05e1f674a 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -95,6 +95,7 @@ typedef struct grib_accessor_g2end_step extern grib_accessor_class* grib_accessor_class_long; + static grib_accessor_class _grib_accessor_class_g2end_step = { &grib_accessor_class_long, /* super */ "g2end_step", /* name */ @@ -177,46 +178,12 @@ static void init(grib_accessor* a, const long l, grib_arguments* c) self->numberOfTimeRange = grib_arguments_get_name(h, c, n++); } + static void dump(grib_accessor* a, grib_dumper* dumper) { grib_dump_double(dumper, a, NULL); } -static const int u2s2[] = { - 60, /* (0) minutes */ - 3600, /* (1) hour */ - 86400, /* (2) day */ - 2592000, /* (3) month */ - -1, /* (4) */ - -1, /* (5) */ - -1, /* (6) */ - -1, /* (7) */ - -1, /* (8) */ - -1, /* (9) */ - 10800, /* (10) 3 hours */ - 21600, /* (11) 6 hours */ - 43200, /* (12) 12 hours */ - 1 /* (13) seconds */ -}; - -static const int u2s[] = { - 60, /* (0) minutes */ - 3600, /* (1) hour */ - 86400, /* (2) day */ - 2592000, /* (3) month */ - -1, /* (4) */ - -1, /* (5) */ - -1, /* (6) */ - -1, /* (7) */ - -1, /* (8) */ - -1, /* (9) */ - 10800, /* (10) 3 hours */ - 21600, /* (11) 6 hours */ - 43200, /* (12) 12 hours */ - 1, /* (13) seconds */ - 900, /* (14) 15 minutes */ - 1800 /* (15) 30 minutes */ -}; /* See GRIB-488 */ static int is_special_expver(grib_handle* h) @@ -232,6 +199,7 @@ static int is_special_expver(grib_handle* h) return 0; } + static int convert_time_range_long_( grib_handle* h, long stepUnits, /* step_units */ @@ -242,34 +210,18 @@ static int convert_time_range_long_( Assert(lengthOfTimeRange != NULL); if (indicatorOfUnitForTimeRange != 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; + Step time_range{*lengthOfTimeRange, indicatorOfUnitForTimeRange}; + time_range.set_unit(Unit{stepUnits}); + if (time_range.value() != time_range.value()) { + return GRIB_DECODING_ERROR; } - 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; + *lengthOfTimeRange = time_range.value(); } return GRIB_SUCCESS; } - static int unpack_one_time_range_long_(grib_accessor* a, long* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; @@ -482,7 +434,6 @@ static int unpack_multiple_time_ranges_double_(grib_accessor* a, double* val, si } - // For the old implementation of unpack_long, see // src/deprecated/grib_accessor_class_g2end_step.unpack_long.cc // @@ -611,16 +562,17 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en return err; if ((err = grib_get_long_internal(h, "startStepUnit", &start_step_unit))) return err; + if (start_step_unit == 255) { - throw std::runtime_error("startStepUnit == 255"); + grib_context_log(h->context, GRIB_LOG_ERROR, + "missing start step unit"); + return GRIB_WRONG_STEP_UNIT; } if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement))) return err; Step start_step{start_step_value, start_step_unit}; - - //time_range_v = *val - start_step_value; Step time_range = end_step - start_step; if (time_range.value() < 0) { @@ -655,37 +607,8 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if ((err = grib_set_long_internal(h, self->second_of_end_of_interval, second_of_end_of_interval))) return err; - //if (time_range_v * u2s[step_units] % u2s2[time_range_unit]) { - // time_range_unit = step_units; - // if ((err = grib_set_long_internal(h, self->time_range_unit, time_range_unit))) - // return err; - // time_range_value = time_range_v; - //} - //else - // time_range_value = (time_range_v * u2s[step_units]) / u2s2[time_range_unit]; - - - //time_range_value = time_range_value * u2s[time_range_unit] / u2s2[step_units]; - //time_range_unit = step_units; - //if ((err = grib_set_long_internal(h, self->time_range_value, time_range_value))) - // return err; - //if ((err = grib_set_long_internal(h, self->time_range_unit, time_range_unit))) - // return err; - - - const char* forecast_time_value_key = "forecastTime"; const char* forecast_time_unit_key = "indicatorOfUnitOfTimeRange"; - //long forecast_time_value; - //long forecast_time_unit; - //if ((err = grib_get_long_internal(h, forecast_time_value_key, &forecast_time_value)) != GRIB_SUCCESS) - // return err; - //if ((err = grib_get_long_internal(h, forecast_time_unit_key, &forecast_time_unit)) != GRIB_SUCCESS) - // return err; - - - //auto [forecast_time, time_range] = find_common_units(Step{forecast_time_value, forecast_time_unit}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); - //auto [forecast_time, time_range] = find_common_units(Step{start_step_value, step_units}.optimize_unit(), Step{time_range_value, time_range_unit}.optimize_unit()); auto [forecast_time_opt, time_range_opt] = find_common_units(start_step.optimize_unit(), time_range.optimize_unit()); if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range_opt.value())) != GRIB_SUCCESS) @@ -697,15 +620,6 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_unit_key, forecast_time_opt.unit().value())) != GRIB_SUCCESS) return err; - - - //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->time_range_value, time_range_value))) - // return err; - //} - return GRIB_SUCCESS; } @@ -749,6 +663,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return GRIB_SUCCESS; } + static int pack_long(grib_accessor* a, const long* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; diff --git a/src/step.cc b/src/step.cc index c402c8e2e..4617927dc 100644 --- a/src/step.cc +++ b/src/step.cc @@ -7,10 +7,9 @@ #include #include +#include "step_unit.h" #include "step.h" - - Step step_from_string(std::string step) { std::regex re("([0-9.]+)([smhDMYC]?)"); @@ -174,6 +173,13 @@ Step& Step::optimize_unit() return *this; } +//Step Step::copy() const { +// Step ret{}; +// ret.internal_value_ = internal_value_; +// ret.internal_unit_ = internal_unit_; +// ret.unit_ = unit_; +// return ret; +//} template <> std::string Step::value(const std::string& format) const { diff --git a/src/step.h b/src/step.h index 98996fe08..63adc89fa 100644 --- a/src/step.h +++ b/src/step.h @@ -114,56 +114,3 @@ template T Step::value(const Unit& unit) const { T value = from_seconds(seconds, unit); return value; } - - -template -Seconds to_seconds(long value, const Unit& unit) { - Seconds seconds; - switch (unit.value()) { - case Unit::Value::SECOND: seconds = Seconds(value); break; - case Unit::Value::MINUTE: seconds = Minutes(value); break; - case Unit::Value::MINUTES15: seconds = Minutes15(value); break; - case Unit::Value::MINUTES30: seconds = Minutes30(value); break; - case Unit::Value::HOUR: seconds = Hours(value); break; - case Unit::Value::HOURS3: seconds = Hours3(value); break; - case Unit::Value::HOURS6: seconds = Hours6(value); break; - case Unit::Value::HOURS12: seconds = Hours12(value); break; - case Unit::Value::DAY: seconds = Days(value); break; - case Unit::Value::MONTH: seconds = Months(value); break; - case Unit::Value::YEAR: seconds = Years(value); break; - case Unit::Value::YEARS10: seconds = Years10(value); break; - case Unit::Value::YEARS30: seconds = Years30(value); break; - case Unit::Value::CENTURY: seconds = Centuries(value); break; - default: - std::string msg = "Unknown unit: " + unit.value(); - throw std::runtime_error(msg); - } - return seconds; -} - - -template -T from_seconds(Seconds seconds, const Unit& unit) { - T value; - switch (unit.value()) { - case Unit::Value::SECOND: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::MINUTE: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::MINUTES15: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::MINUTES30: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::HOUR: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::HOURS3: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::HOURS6: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::HOURS12: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::DAY: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::MONTH: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::YEAR: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::YEARS10: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::YEARS30: value = std::chrono::duration_cast>(seconds).count(); break; - case Unit::Value::CENTURY: value = std::chrono::duration_cast>(seconds).count(); break; - default: - std::string msg = "Unknown unit: " + unit.value(); - throw std::runtime_error(msg); - } - return value; -} - diff --git a/src/step_unit.h b/src/step_unit.h index 1c5c0b196..aa827674d 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -64,11 +65,6 @@ public: return *this; } - //std::string to_string() const { - // return map_.unit_to_name(internal_value_); - //} - //long to_long() const {return map_.unit_to_long(internal_value_);} - //Value to_value() const {return internal_value_;} template T value() const; static std::vector unit_order_; static std::vector complete_unit_order_; @@ -145,3 +141,56 @@ private: public: static Map& get_converter() {return map_;} }; + + + +template +Seconds to_seconds(long value, const Unit& unit) { + Seconds seconds; + switch (unit.value()) { + case Unit::Value::SECOND: seconds = Seconds(value); break; + case Unit::Value::MINUTE: seconds = Minutes(value); break; + case Unit::Value::MINUTES15: seconds = Minutes15(value); break; + case Unit::Value::MINUTES30: seconds = Minutes30(value); break; + case Unit::Value::HOUR: seconds = Hours(value); break; + case Unit::Value::HOURS3: seconds = Hours3(value); break; + case Unit::Value::HOURS6: seconds = Hours6(value); break; + case Unit::Value::HOURS12: seconds = Hours12(value); break; + case Unit::Value::DAY: seconds = Days(value); break; + case Unit::Value::MONTH: seconds = Months(value); break; + case Unit::Value::YEAR: seconds = Years(value); break; + case Unit::Value::YEARS10: seconds = Years10(value); break; + case Unit::Value::YEARS30: seconds = Years30(value); break; + case Unit::Value::CENTURY: seconds = Centuries(value); break; + default: + std::string msg = "Unknown unit: " + unit.value(); + throw std::runtime_error(msg); + } + return seconds; +} + + +template +T from_seconds(Seconds seconds, const Unit& unit) { + T value; + switch (unit.value()) { + case Unit::Value::SECOND: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::MINUTE: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::MINUTES15: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::MINUTES30: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::HOUR: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::HOURS3: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::HOURS6: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::HOURS12: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::DAY: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::MONTH: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::YEAR: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::YEARS10: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::YEARS30: value = std::chrono::duration_cast>(seconds).count(); break; + case Unit::Value::CENTURY: value = std::chrono::duration_cast>(seconds).count(); break; + default: + std::string msg = "Unknown unit: " + unit.value(); + throw std::runtime_error(msg); + } + return value; +} From de4178e33d1633c7e7922df016fb1ef59e529b79 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 21 Sep 2023 12:51:19 +0000 Subject: [PATCH 048/125] ECC-1620: Clean step_in_units --- src/grib_accessor_class_step_in_units.cc | 110 ++--------------------- 1 file changed, 7 insertions(+), 103 deletions(-) diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index e10a14f39..4ab5b2b47 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -123,11 +123,11 @@ static void init(grib_accessor* a, const long l, grib_arguments* c) grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; int n = 0; - self->forecast_time_value = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->forecast_time_unit = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->step_units = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->time_range_unit = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); - self->time_range_value = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->forecast_time_value = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->forecast_time_unit = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->step_units = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->time_range_unit = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); + self->time_range_value = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); } static void dump(grib_accessor* a, grib_dumper* dumper) @@ -135,44 +135,6 @@ static void dump(grib_accessor* a, grib_dumper* dumper) grib_dump_double(dumper, a, NULL); } -/* Conversion of to seconds - Grib edition 2 table 4.4 */ -static const int u2s2[] = { - 60, /* (0) minutes */ - 3600, /* (1) hour */ - 86400, /* (2) day */ - 2592000, /* (3) month */ - -1, /* (4) year */ - -1, /* (5) decade */ - -1, /* (6) 30 years */ - -1, /* (7) century */ - -1, /* (8) RESERVED */ - -1, /* (9) RESERVED */ - 10800, /* (10) 3 hours */ - 21600, /* (11) 6 hours */ - 43200, /* (12) 12 hours */ - 1 /* (13) seconds */ -}; - -/* Note: 'step_units' has a different table with extra entries e.g. 15 and 30 mins */ -static const int u2s[] = { - 60, /* (0) minutes */ - 3600, /* (1) hour */ - 86400, /* (2) day */ - 2592000, /* (3) month */ - -1, /* (4) year */ - -1, /* (5) decade */ - -1, /* (6) 30 years */ - -1, /* (7) century */ - -1, /* (8) */ - -1, /* (9) */ - 10800, /* (10) 3 hours */ - 21600, /* (11) 6 hours */ - 43200, /* (12) 12 hours */ - 1, /* (13) seconds */ - 900, /* (14) 15 minutes */ - 1800 /* (15) 30 minutes */ -}; - static int unpack_long(grib_accessor* a, long* val, size_t* len) { @@ -229,70 +191,15 @@ static int unpack_double(grib_accessor* a, double * val, size_t* len) } -int pack_long_old_(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 err = 0; - long forecast_time_value, forecast_time_unit, step_units; - long oldStep = 0; - long time_range_unit, time_range_value; - - if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit))) - return err; - if ((err = grib_get_long_internal(h, self->step_units, &step_units))) - return err; - - unpack_long(a, &oldStep, len); - - if (step_units != forecast_time_unit) { - forecast_time_value = *val * u2s[step_units]; - if (forecast_time_value % u2s2[forecast_time_unit] != 0) { - forecast_time_unit = step_units; - err = grib_set_long_internal(h, self->forecast_time_unit, forecast_time_unit); - if (err != GRIB_SUCCESS) - return err; - forecast_time_value = *val; - } - else { - forecast_time_value = forecast_time_value / u2s2[forecast_time_unit]; - } - } - else { - forecast_time_value = *val; - } - - if (self->time_range_unit) { - if ((err = grib_get_long_internal(h, - self->time_range_unit, &time_range_unit))) - return err; - if ((err = grib_get_long_internal(h, - self->time_range_value, &time_range_value))) - return err; - if (forecast_time_unit == time_range_unit) - time_range_value -= forecast_time_value - oldStep; - else - time_range_value -= forecast_time_value * u2s2[forecast_time_unit] / u2s2[time_range_unit]; - time_range_value = time_range_value > 0 ? time_range_value : 0; - err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range_value); - if (err != GRIB_SUCCESS) - return err; - } - - return grib_set_long_internal(grib_handle_of_accessor(a), self->forecast_time_value, forecast_time_value); -} - int pack_long_new_(grib_accessor* a, const long start_step_value, const long start_step_unit) { grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); int err = 0; - //long forecast_time_value; long forecast_time_unit; long step_units; long start_step_value_old; long start_step_unit_old; size_t len = 0; - //long time_range_unit; - //long time_range_value; if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit)) != GRIB_SUCCESS) return err; @@ -301,9 +208,6 @@ int pack_long_new_(grib_accessor* a, const long start_step_value, const long sta if ((err = grib_get_long_internal(h, "startStepUnit", &start_step_unit_old)) != GRIB_SUCCESS) return err; - //if ((err = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) - //return err; - //step_units = get_step_units(h); Step start_step_old(start_step_value_old, start_step_unit_old); Step forecast_time(start_step_value, start_step_unit); Step time_range_new{}; @@ -334,6 +238,7 @@ int pack_long_new_(grib_accessor* a, const long start_step_value, const long sta return GRIB_SUCCESS; } + static int pack_long(grib_accessor* a, const long* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); @@ -360,6 +265,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return ret; } + 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; @@ -411,5 +317,3 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return GRIB_SUCCESS; } - - From 97830f57b8b3978c6b05dbb73770bcc7c7c1630f Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 21 Sep 2023 12:57:08 +0000 Subject: [PATCH 049/125] ECC-1620: Cleanup tests --- tests/grib_ecc-1620.sh | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 8dd22a0e5..5ca007453 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -52,6 +52,13 @@ low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indi ${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" +### TODO(EB): @Shahram: how to make parameters position independent +${tools_dir}/grib_set -s stepUnits:s=s,startStep:i=60,endStep:i=180 $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" +#${tools_dir}/grib_set -s startStep:i=60,endStep:i=180,stepUnits:s=s $temp $temp2 +#grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" + + ${tools_dir}/grib_set -s stepUnits:i=13,startStep:i=60,endStep:i=180 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" ${tools_dir}/grib_set -s stepUnits:s=s,startStep:i=60,endStep:i=180 $temp $temp2 @@ -101,44 +108,32 @@ ${tools_dir}/grib_set -s endStep:d=30 $temp $temp2 # TODO(EB) remove in the futu #${tools_dir}/grib_set -s endStep:s=30h $temp $temp2 #${tools_dir}/grib_set -s endStep=30h $temp $temp2 # TODO(EB) add to tests grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 6 h" -#${tools_dir}/grib_set -s endStep:d=24.5 $temp $temp2 -#grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 30 m" # Use stepUnits ${tools_dir}/grib_set -s endStep:s=30 $temp $temp2 +grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 6 h" + ${tools_dir}/grib_set -s endStep:s=30h $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 6 h" -#${tools_dir}/grib_set -s endStep:s=24.5h $temp $temp2 -#grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 30 m" + ${tools_dir}/grib_set -s endStep:s=88200s $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "1440 m 30 m" -#${tools_dir}/grib_set -s endStep:s=1446.65m $temp $temp2 -#grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 399 s" + ${tools_dir}/grib_set -s endStep:s=24024 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 24000 h" -# Use range unit: hour ${tools_dir}/grib_set -s startStep:d=5 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "5 h 43 h" -#${tools_dir}/grib_set -s startStep:d=4.5 $temp $temp2 -#grib_check_key_equals $temp2 "-p $low_level_keys" "270 m 1 D" -# Use stepUnits ${tools_dir}/grib_set -s startStep:s=5h $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "5 h 43 h" -#${tools_dir}/grib_set -s startStep:s=4.5h $temp $temp2 -#grib_check_key_equals $temp2 "-p $low_level_keys" "270 m 1 D" + ${tools_dir}/grib_set -s startStep:s=240s $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "4 m 2876 m" -#${tools_dir}/grib_set -s startStep:s=0.65m $temp $temp2 -#grib_check_key_equals $temp2 "-p $low_level_keys" "39 s 1 D" + ${tools_dir}/grib_set -s startStep:s=2 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "2 h 46 h" - - - - ${tools_dir}/grib_set -s stepRange:s=5h-30h $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "5 h 25 h" grib_check_key_equals $temp2 "-p stepRange:s" "5-30" From b98039e652155d4c13771483aacf222c47d1c6da Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 21 Sep 2023 15:57:11 +0000 Subject: [PATCH 050/125] ECC-1620: Minor changes --- src/grib_accessor_class_step_in_units.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 4ab5b2b47..d8947b7fd 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -170,8 +170,6 @@ static int unpack_double(grib_accessor* a, double * val, size_t* len) int err = 0; long forecast_time_value, forecast_time_unit, step_units; grib_handle* h = grib_handle_of_accessor(a); - int factor = 0; - long u2sf, u2sf_step_unit; if ((err= grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return err; From b38aedd57e875de2acbbd91c6910d327fe6cd6bb Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 21 Sep 2023 17:02:09 +0000 Subject: [PATCH 051/125] ECC-1620: Fix grib_set test --- src/grib_accessor_class_optimal_step_units.cc | 10 ++++++++-- tests/grib_set.sh | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 384c3800e..8eab3a9ed 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -191,8 +191,14 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { - long unit = Unit{val}.value(); - pack_long(a, &unit, len); + try { + long unit = Unit{val}.value(); + pack_long(a, &unit, len); + } + catch (std::exception& e) { + grib_context_log(a->context, GRIB_LOG_ERROR, "Invalid unit: %s", val); + return GRIB_INVALID_ARGUMENT; + } return GRIB_SUCCESS; } diff --git a/tests/grib_set.sh b/tests/grib_set.sh index 1b8be144b..0489c61c3 100755 --- a/tests/grib_set.sh +++ b/tests/grib_set.sh @@ -223,7 +223,8 @@ ${tools_dir}/grib_set -s stepUnits=d $input $outfile > $temp 2>&1 status=$? set -e [ $status -ne 0 ] -grep -q "stepUnits: No such code table entry.*Did you mean" $temp +grep -q "Invalid argument" $temp +#grep -q "stepUnits: No such code table entry.*Did you mean" $temp # ------------------------ # Unreadable message From 65193dfd89324859b5c7b5e61f5b00e8c3705ec6 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 22 Sep 2023 10:25:34 +0000 Subject: [PATCH 052/125] ECC-1620: Change mars.step unit from string to undefined --- tools/grib_tools.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/grib_tools.cc b/tools/grib_tools.cc index 0cfef8449..2d78e0a98 100644 --- a/tools/grib_tools.cc +++ b/tools/grib_tools.cc @@ -776,6 +776,9 @@ static void grib_tools_set_print_keys(grib_runtime_options* options, grib_handle if (strlen(name) > options->default_print_width) options->default_print_width = (int)strlen(name); options->print_keys[options->print_keys_count].type = GRIB_TYPE_STRING; + if (strcmp(ns, "mars") == 0 && (strcmp(name, "step") == 0)) { + options->print_keys[options->print_keys_count].type = GRIB_TYPE_UNDEFINED; + } // For the statistics namespace, do not force the type to be string. // Setting it to undefined will use the keys' native type i.e. GRIB_TYPE_DOUBLE if (strcmp(ns,"statistics")==0) From bd69d15d13ea4d4176d649a252a2db200da76198 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 22 Sep 2023 10:26:12 +0000 Subject: [PATCH 053/125] ECC-1620: Clean up --- src/grib_accessor_class_g2end_step.cc | 8 ++------ src/grib_accessor_class_g2step_range.cc | 5 +++-- src/grib_accessor_class_optimal_step_units.cc | 1 - src/grib_accessor_class_step_in_units.cc | 7 ------- src/step_unit.h | 4 ++-- 5 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 05e1f674a..f04850488 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -523,15 +523,14 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en long start_step_value; long start_step_unit; - long step_units, time_range_unit; + long time_range_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; - - long time_range_value, time_range_v, typeOfTimeIncrement; + long typeOfTimeIncrement; double dend, dstep; @@ -636,7 +635,6 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) long step_value; long step_units; - if ((ret = unpack_long(a, &step_value, &step_len)) != GRIB_SUCCESS) return ret; if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS) @@ -666,7 +664,6 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) 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; @@ -692,7 +689,6 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) 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); diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 7ece162f0..8178ac7f0 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -25,6 +25,7 @@ SUPER = grib_accessor_class_gen IMPLEMENTS = pack_string;unpack_string;value_count IMPLEMENTS = unpack_long;pack_long + IMPLEMENTS = unpack_double IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = get_native_type;string_length IMPLEMENTS = init @@ -48,6 +49,7 @@ static int get_native_type(grib_accessor*); 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_long(grib_accessor*, long* val, size_t* len); +static int unpack_double(grib_accessor*, double* 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*); @@ -87,7 +89,7 @@ static grib_accessor_class _grib_accessor_class_g2step_range = { &unpack_long, /* unpack_long */ 0, /* pack_double */ 0, /* pack_float */ - 0, /* unpack_double */ + &unpack_double, /* unpack_double */ 0, /* unpack_float */ &pack_string, /* pack_string */ &unpack_string, /* unpack_string */ @@ -138,7 +140,6 @@ static int unpack_string(grib_accessor* a, char* 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; double start_step_value = 0; diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 8eab3a9ed..0daaefa26 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -147,7 +147,6 @@ static long staticForceStepUnits = Unit{Unit::Value::MISSING}.value(); static int pack_long(grib_accessor* a, const long* val, size_t* len) { - grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; grib_handle* h = grib_handle_of_accessor(a); int ret; diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index d8947b7fd..b4a2e0056 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -142,8 +142,6 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) int err = 0; long forecast_time_value, forecast_time_unit, step_units; grib_handle* h = grib_handle_of_accessor(a); - int factor = 0; - long u2sf, u2sf_step_unit; if ((err= grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return err; @@ -194,7 +192,6 @@ int pack_long_new_(grib_accessor* a, const long start_step_value, const long sta grib_handle* h = grib_handle_of_accessor(a); int err = 0; long forecast_time_unit; - long step_units; long start_step_value_old; long start_step_unit_old; size_t len = 0; @@ -266,11 +263,7 @@ static int pack_long(grib_accessor* a, const long* 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; - size_t value_len = 0; - Step step = step_from_string(val); if ((ret = pack_long_new_(a, step.value(), step.unit().value())) != GRIB_SUCCESS) diff --git a/src/step_unit.h b/src/step_unit.h index aa827674d..8fd16d77a 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -107,7 +107,7 @@ private: long duration; }; - const std::array tab_ = { + const std::array tab_ = {{ Entry{Value::MISSING , "MISSING" , 0}, Entry{Value::SECOND , "s" , 1}, Entry{Value::MINUTE , "m" , 60}, @@ -123,7 +123,7 @@ private: Entry{Value::YEARS10 , "10Y" , 315360000}, Entry{Value::YEARS30 , "30Y" , 946080000}, Entry{Value::CENTURY , "C" , 3153600000}, - }; + }}; std::unordered_map name_to_value_; std::unordered_map value_to_name_; From aef6905224815243ea193f230507b5dc1828b8ce Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 22 Sep 2023 10:55:09 +0000 Subject: [PATCH 054/125] ECC-1620: Fix stepUnits, when value == 0 --- src/grib_accessor_class_step_in_units.cc | 1 + src/step.cc | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index b4a2e0056..acd725b10 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -151,6 +151,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) return err; Step step{forecast_time_value, forecast_time_unit}; + step.optimize_unit(); if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.value())) != GRIB_SUCCESS) return err; diff --git a/src/step.cc b/src/step.cc index 4617927dc..3e67b5216 100644 --- a/src/step.cc +++ b/src/step.cc @@ -154,6 +154,9 @@ void Step::init_double(double value, const Unit& unit) Step& Step::optimize_unit() { if (internal_value_ == 0) { + if (unit() > Unit{Unit::Value::HOUR}) { + set_unit(Unit{Unit::Value::HOUR}); + } return *this; } From c241db010723eb762abc1a71d9af95473b4afdc6 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 22 Sep 2023 11:10:30 +0000 Subject: [PATCH 055/125] ECC-1620: Change mars.stepUnits to mars.stepunits --- definitions/grib2/products_s2s.def | 2 +- definitions/grib2/template.4.localtime.def | 2 +- definitions/grib2/template.4.point_in_time.def | 4 ++-- definitions/grib2/template.4.statistical.def | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/definitions/grib2/products_s2s.def b/definitions/grib2/products_s2s.def index a20c733ee..09238eb49 100644 --- a/definitions/grib2/products_s2s.def +++ b/definitions/grib2/products_s2s.def @@ -73,7 +73,7 @@ alias mars.type = marsType; # Normally MARS step is endStep but for monthly means we want stepRange if (stepType is "avg") { alias mars.step = stepRange; - alias mars.stepUnits = stepUnits; + alias mars.stepunits = stepUnits; } if (isHindcast == 1) { diff --git a/definitions/grib2/template.4.localtime.def b/definitions/grib2/template.4.localtime.def index f1d533a84..f37c5c3aa 100644 --- a/definitions/grib2/template.4.localtime.def +++ b/definitions/grib2/template.4.localtime.def @@ -82,7 +82,7 @@ if (numberOfForecastsUsedInLocalTime == 1) { alias mars.date = dateOfForecastUsedInLocalTime : dump; alias mars.time = timeOfForecastUsedInLocalTime : dump; alias mars.step = endStep; - alias mars.stepUnits = stepUnits; + alias mars.stepunits = stepUnits; alias time.dataDate = dateOfForecastUsedInLocalTime; alias time.dataTime = timeOfForecastUsedInLocalTime; alias time.endStep = endStep; diff --git a/definitions/grib2/template.4.point_in_time.def b/definitions/grib2/template.4.point_in_time.def index 7164d8dbb..f32d04ba1 100644 --- a/definitions/grib2/template.4.point_in_time.def +++ b/definitions/grib2/template.4.point_in_time.def @@ -7,7 +7,7 @@ alias step=startStep; alias marsStep=startStep; alias mars.step=startStep; -alias mars.stepUnits=stepUnits; +alias mars.stepunits=stepUnits; alias marsStartStep = startStep; alias marsEndStep = endStep; @@ -21,7 +21,7 @@ meta stepHumanReadable step_human_readable(stepUnits, stepRange): hidden,no_copy alias time.stepType=stepType; alias time.stepRange=stepRange; -alias time.stepUnits=stepUnits; +alias time.stepunits=stepUnits; alias time.dataDate=dataDate; alias time.dataTime=dataTime; alias time.startStep=startStep; diff --git a/definitions/grib2/template.4.statistical.def b/definitions/grib2/template.4.statistical.def index 810379d86..a726ca1c0 100644 --- a/definitions/grib2/template.4.statistical.def +++ b/definitions/grib2/template.4.statistical.def @@ -111,7 +111,7 @@ if (numberOfTimeRange == 1 || numberOfTimeRange == 2) { alias ls.stepRange=stepRange; alias mars.step=endStep; -alias mars.stepUnits=stepUnits; +alias mars.stepunits=stepUnits; alias time.stepType=stepType; alias time.stepRange=stepRange; From 72ac273cc0eb7a4d9a1f58784a1f06d4f890e77f Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 22 Sep 2023 11:10:49 +0000 Subject: [PATCH 056/125] ECC-1620: Change 255 to Unit{Unit::Value::MISSING} --- src/grib_accessor_class_g2end_step.cc | 6 +++--- src/grib_accessor_class_g2step_range.cc | 7 ++++--- src/grib_accessor_class_optimal_step_units.cc | 2 +- src/grib_accessor_class_step_in_units.cc | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index f04850488..efecc9302 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -562,7 +562,7 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if ((err = grib_get_long_internal(h, "startStepUnit", &start_step_unit))) return err; - if (start_step_unit == 255) { + if (Unit{start_step_unit} == Unit{Unit::Value::MISSING}) { grib_context_log(h->context, GRIB_LOG_ERROR, "missing start step unit"); return GRIB_WRONG_STEP_UNIT; @@ -672,11 +672,11 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return ret; long end_step_unit; - if (force_step_units == 255) { + if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { if ((ret = grib_get_long_internal(h, "endStepUnit", &end_step_unit)) != GRIB_SUCCESS) return ret; - if (end_step_unit == 255) + if (Unit{end_step_unit} == Unit{Unit::Value::MISSING}) end_step_unit = Unit{Unit::Value::HOUR}.value(); } else { diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 8178ac7f0..5af96847f 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -150,7 +150,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; if ((ret= grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; - if (step_units == 255) { + if (Unit{step_units} == Unit{Unit::Value::MISSING}) { if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; } @@ -291,7 +291,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) return ret; if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) throw std::runtime_error("Failed to get stepUnits"); - if (step_units == 255) { + if (Unit{step_units} == Unit{Unit::Value::MISSING}) { if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; } @@ -324,7 +324,8 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) return ret; if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) throw std::runtime_error("Failed to get stepUnits"); - if (step_units == 255) { + + if (Unit{step_units} == Unit{Unit::Value::MISSING}) { if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; } diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 0daaefa26..7a9316952 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -160,7 +160,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) static int unpack_long(grib_accessor* a, long* val, size_t* len) { - if (staticStepUnits != 255) { + if (Unit{staticStepUnits} != Unit{Unit::Value::MISSING}) { *val = staticStepUnits; return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index acd725b10..dd4fd6ebc 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -245,11 +245,11 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return ret; long start_step_unit; - if (force_step_units == 255) { + if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { if ((ret = grib_get_long_internal(h, "startStepUnit", &start_step_unit)) != GRIB_SUCCESS) return ret; - if (start_step_unit == 255) + if (Unit{start_step_unit} == Unit{Unit::Value::MISSING}) start_step_unit = Unit{Unit::Value::HOUR}.value(); } else { From 89a0a0e870cfc6e8e4e19554be44f85cbcd67972 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 22 Sep 2023 11:17:02 +0000 Subject: [PATCH 057/125] ECC-1620: Adapt mars tests --- tests/grib_ecc-1212.sh | 2 +- tests/grib_mars_keys1.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/grib_ecc-1212.sh b/tests/grib_ecc-1212.sh index 286e9c0de..f52026594 100755 --- a/tests/grib_ecc-1212.sh +++ b/tests/grib_ecc-1212.sh @@ -59,7 +59,7 @@ cat > $tempRef < $tempRef << EOF "class": "od", "type": "an", "stream": "oper", - "stepUnits": "h", + "stepunits": "h", "step": 0, "levelist": 1000, "levtype": "pl", @@ -69,7 +69,7 @@ cat > $tempRef << EOF "class": "od", "type": "pf", "stream": "enfo", - "stepUnits": "h", + "stepunits": "h", "step": 0, "levelist": 1000, "levtype": "pl", From d0189a5df5cb59fa312c946a0324470e8c6a1ff1 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 22 Sep 2023 13:44:23 +0000 Subject: [PATCH 058/125] ECC-1620: GRIB1: mars.stepUnits to mars.stepunits --- definitions/grib1/section.1.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/definitions/grib1/section.1.def b/definitions/grib1/section.1.def index f962f0aeb..0032f6117 100644 --- a/definitions/grib1/section.1.def +++ b/definitions/grib1/section.1.def @@ -224,7 +224,7 @@ alias ls.stepRange = stepRange; alias ls.dataDate = dataDate; alias mars.step = endStep; -alias mars.stepUnits = stepUnits; +alias mars.stepunits = stepUnits; alias mars.date = dataDate; alias mars.levtype = indicatorOfTypeOfLevel; alias mars.time = dataTime; From 6c1df597f7c7b655f2c529c292c0446495ca3574 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Wed, 4 Oct 2023 12:54:20 +0100 Subject: [PATCH 059/125] Add copyright notices --- src/step.cc | 19 ++++++++++--------- src/step_unit.cc | 10 ++++++++++ src/step_utilities.cc | 13 ++++++++++--- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/step.cc b/src/step.cc index 3e67b5216..b6f4afef3 100644 --- a/src/step.cc +++ b/src/step.cc @@ -1,3 +1,13 @@ +/* + * (C) Copyright 2005- ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * + * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by + * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. + */ + #include #include #include @@ -28,7 +38,6 @@ Step step_from_string(std::string step) throw std::runtime_error("Could not parse step: " + step); } - std::vector parse_range(const std::string& range_str) { std::vector steps; @@ -42,7 +51,6 @@ std::vector parse_range(const std::string& range_str) return steps; } - bool Step::operator==(const Step& other) const { if ((internal_value_ == other.internal_value_) && (internal_unit_ == other.internal_unit_)) { @@ -51,7 +59,6 @@ bool Step::operator==(const Step& other) const return false; } - bool Step::operator>(const Step& step) const { auto [a, b] = find_common_units(this->copy().optimize_unit(), step.copy().optimize_unit()); @@ -59,7 +66,6 @@ bool Step::operator>(const Step& step) const return a.internal_value_ > b.internal_value_; } - bool Step::operator<(const Step& step) const { auto [a, b] = find_common_units(this->copy().optimize_unit(), step.copy().optimize_unit()); @@ -67,7 +73,6 @@ bool Step::operator<(const Step& step) const return a.internal_value_ < b.internal_value_; } - Step Step::operator+(const Step& step) const { Step tmp = step; @@ -76,7 +81,6 @@ Step Step::operator+(const Step& step) const return Step(a.internal_value_ + b.internal_value_, a.internal_unit_); } - Step Step::operator-(const Step& step) const { Step tmp = step; @@ -85,7 +89,6 @@ Step Step::operator-(const Step& step) const return Step(a.internal_value_ - b.internal_value_, a.internal_unit_); } - std::pair find_common_units(const Step& startStep, const Step& endStep) { Step a = startStep; @@ -135,7 +138,6 @@ void Step::sanity_check() const //} } - void Step::init_long(long value, const Unit& unit) { internal_value_ = value; @@ -201,4 +203,3 @@ std::string Step::value(const std::string& format) const { } return output; } - diff --git a/src/step_unit.cc b/src/step_unit.cc index 3c450fcf2..4fb323586 100644 --- a/src/step_unit.cc +++ b/src/step_unit.cc @@ -1,3 +1,13 @@ +/* + * (C) Copyright 2005- ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * + * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by + * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. + */ + #include "step_unit.h" Unit::Map Unit::map_{}; diff --git a/src/step_utilities.cc b/src/step_utilities.cc index cbea1621d..e4e4b02d4 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -1,7 +1,16 @@ +/* + * (C) Copyright 2005- ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * + * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by + * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. + */ + #include "step_utilities.h" #include - std::optional get_step(grib_handle* h, const char* value_key, const char* unit_key) { if (value_key && unit_key && grib_is_defined(h, unit_key) && grib_is_defined(h, value_key)) { @@ -20,7 +29,6 @@ std::optional get_step(grib_handle* h, const char* value_key, const char* } } - int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step) { int err; @@ -33,7 +41,6 @@ int set_step(grib_handle* h, const std::string& value_key, const std::string& un return GRIB_SUCCESS; } - bool is_future_output_enabled(grib_handle* h) { return h->context->is_future_step_format > 0; From 01ab2de0febff437dd5fda37546baf0189ebfe8d Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Wed, 4 Oct 2023 13:07:55 +0100 Subject: [PATCH 060/125] Add copyright notices --- src/step.h | 10 ++++++++++ src/step_unit.h | 10 ++++++++++ src/step_utilities.h | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/src/step.h b/src/step.h index 63adc89fa..cc7eec47d 100644 --- a/src/step.h +++ b/src/step.h @@ -1,3 +1,13 @@ +/* + * (C) Copyright 2005- ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * + * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by + * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. + */ + #pragma once #include diff --git a/src/step_unit.h b/src/step_unit.h index 8fd16d77a..bffb67715 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -1,3 +1,13 @@ +/* + * (C) Copyright 2005- ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * + * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by + * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. + */ + #pragma once #include diff --git a/src/step_utilities.h b/src/step_utilities.h index 5259a0ed3..eac3b2619 100644 --- a/src/step_utilities.h +++ b/src/step_utilities.h @@ -1,3 +1,13 @@ +/* + * (C) Copyright 2005- ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * + * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by + * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. + */ + #pragma once #include "grib_api_internal.h" From d614da57e72860cb32a091841beaa1e2bb8b3d20 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Wed, 4 Oct 2023 13:08:12 +0100 Subject: [PATCH 061/125] Do not use variable-length arrays --- src/step.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/step.cc b/src/step.cc index b6f4afef3..629143c34 100644 --- a/src/step.cc +++ b/src/step.cc @@ -189,7 +189,7 @@ Step& Step::optimize_unit() template <> std::string Step::value(const std::string& format) const { constexpr int max_size = 128; - char output[max_size]; + char output[128]; //Do not use variable-length arrays std::string u; if (unit_ == Unit::Value::HOUR) From ef45cef6e8f20f1c6bfe7c8e2b5a2ac42eb5a477 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Wed, 4 Oct 2023 13:17:18 +0000 Subject: [PATCH 062/125] Remove duplicated include --- src/step.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/step.h b/src/step.h index cc7eec47d..2397e77d3 100644 --- a/src/step.h +++ b/src/step.h @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include From 09c2c670493affc929a438487eed1f814fff91ef Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 9 Oct 2023 10:57:33 +0000 Subject: [PATCH 063/125] Remove future step format --- src/grib_api_internal.h | 1 - src/grib_context.cc | 6 +----- src/step_utilities.cc | 5 ----- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/grib_api_internal.h b/src/grib_api_internal.h index 3aa41ef77..bf6b3694d 100644 --- a/src/grib_api_internal.h +++ b/src/grib_api_internal.h @@ -1067,7 +1067,6 @@ struct grib_context grib_trie* lists; grib_trie* expanded_descriptors; int file_pool_max_opened_files; - int is_future_step_format; #if GRIB_PTHREADS pthread_mutex_t mutex; #elif GRIB_OMP_THREADS diff --git a/src/grib_context.cc b/src/grib_context.cc index b5c8c0a2f..8f52633eb 100644 --- a/src/grib_context.cc +++ b/src/grib_context.cc @@ -361,8 +361,7 @@ static grib_context default_grib_context = { 0, /* classes */ 0, /* lists */ 0, /* expanded_descriptors */ - DEFAULT_FILE_POOL_MAX_OPENED_FILES, /* file_pool_max_opened_files */ - 0 + DEFAULT_FILE_POOL_MAX_OPENED_FILES /* file_pool_max_opened_files */ #if GRIB_PTHREADS , PTHREAD_MUTEX_INITIALIZER /* mutex */ @@ -395,7 +394,6 @@ grib_context* grib_context_get_default() const char* grib_data_quality_checks = NULL; const char* single_precision = NULL; const char* file_pool_max_opened_files = NULL; - const char* is_future_step_format = NULL; #ifdef ENABLE_FLOATING_POINT_EXCEPTIONS feenableexcept(FE_ALL_EXCEPT & ~FE_INEXACT); @@ -418,7 +416,6 @@ grib_context* grib_context_get_default() no_spd = codes_getenv("ECCODES_GRIB_NO_SPD"); keep_matrix = codes_getenv("ECCODES_GRIB_KEEP_MATRIX"); file_pool_max_opened_files = getenv("ECCODES_FILE_POOL_MAX_OPENED_FILES"); - is_future_step_format = getenv("ECCODES_GRIB_IS_FUTURE_STEP_FORMAT"); /* On UNIX, when we read from a file we get exactly what is in the file on disk. * But on Windows a file can be opened in binary or text mode. In binary mode the system behaves exactly as in UNIX. @@ -553,7 +550,6 @@ grib_context* grib_context_get_default() default_grib_context.grib_data_quality_checks = grib_data_quality_checks ? atoi(grib_data_quality_checks) : 0; default_grib_context.single_precision = single_precision ? atoi(single_precision) : 0; default_grib_context.file_pool_max_opened_files = file_pool_max_opened_files ? atoi(file_pool_max_opened_files) : DEFAULT_FILE_POOL_MAX_OPENED_FILES; - default_grib_context.is_future_step_format = is_future_step_format ? atoi(is_future_step_format) : 0; } GRIB_MUTEX_UNLOCK(&mutex_c); diff --git a/src/step_utilities.cc b/src/step_utilities.cc index e4e4b02d4..d6f244acd 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -40,8 +40,3 @@ int set_step(grib_handle* h, const std::string& value_key, const std::string& un return err; return GRIB_SUCCESS; } - -bool is_future_output_enabled(grib_handle* h) -{ - return h->context->is_future_step_format > 0; -} From efd64951fbdb38179b02396c452d2f3cc5e45fb4 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 11 Oct 2023 11:48:04 +0000 Subject: [PATCH 064/125] ECC-1620: Remove future format --- tools/grib_get.cc | 1 - tools/grib_ls.cc | 1 - tools/grib_options.cc | 6 +----- tools/grib_set.cc | 1 - tools/grib_tools.cc | 9 +-------- tools/grib_tools.h | 2 -- 6 files changed, 2 insertions(+), 18 deletions(-) diff --git a/tools/grib_get.cc b/tools/grib_get.cc index 8ce60d7eb..12acb78da 100644 --- a/tools/grib_get.cc +++ b/tools/grib_get.cc @@ -15,7 +15,6 @@ grib_option grib_options[] = { { "f", 0, 0, 0, 1, 0 }, { "p:", 0, 0, 0, 1, 0 }, { "F:", 0, 0, 1, 1, "%g" }, - { "y", 0, 0, 0, 1, 0 }, { "B:", 0, 0, 0, 1, 0 }, { "l:", 0, 0, 0, 1, 0 }, { "P:", 0, 0, 0, 1, 0 }, diff --git a/tools/grib_ls.cc b/tools/grib_ls.cc index b15263576..0193b3e17 100644 --- a/tools/grib_ls.cc +++ b/tools/grib_ls.cc @@ -15,7 +15,6 @@ grib_option grib_options[] = { { "f", 0, 0, 1, 0, 0 }, { "p:", 0, 0, 0, 1, 0 }, { "F:", 0, 0, 1, 1, "%g" }, - { "y", 0, 0, 0, 1, 0 }, { "P:", 0, 0, 0, 1, 0 }, { "w:", 0, 0, 0, 1, 0 }, { "j", 0, "JSON output\n", 0, 1, 0 }, diff --git a/tools/grib_options.cc b/tools/grib_options.cc index 1b4c0c98b..475f22fdf 100644 --- a/tools/grib_options.cc +++ b/tools/grib_options.cc @@ -232,7 +232,7 @@ int grib_process_runtime_options(grib_context* context, int argc, char** argv, g if (grib_options_on("F:")) options->format = grib_options_get_option("F:"); else - options->format = NULL; + options->format = strdup("%g"); if (grib_options_on("i:")) { options->index_on = 1; @@ -250,10 +250,6 @@ int grib_process_runtime_options(grib_context* context, int argc, char** argv, g if (grib_options_on("X:")) options->infile_offset = atol(grib_options_get_option("X:")); - if (grib_options_on("y")) { - options->step_output_format = strdup("future"); - } - #ifndef ECCODES_ON_WINDOWS /* Check at compile time to ensure our file offset is at least 64 bits */ COMPILE_TIME_ASSERT(sizeof(options->infile_offset) >= 8); diff --git a/tools/grib_set.cc b/tools/grib_set.cc index b805c5f66..13adcde65 100644 --- a/tools/grib_set.cc +++ b/tools/grib_set.cc @@ -15,7 +15,6 @@ grib_option grib_options[] = { { "s:", 0, 0, 1, 1, 0 }, { "r", 0, 0, 0, 1, 0 }, { "d:", 0, 0, 0, 1, 0 }, - { "y", 0, 0, 0, 1, 0 }, /*{"n:","noise percentage","\n\t\tAdd noise to the data values. The noise added is the given percentage of the data value.\n",0,1,0},*/ { "p:", 0, 0, 1, 1, 0 }, { "P:", 0, 0, 0, 1, 0 }, diff --git a/tools/grib_tools.cc b/tools/grib_tools.cc index 7190610ca..fc5637ab6 100644 --- a/tools/grib_tools.cc +++ b/tools/grib_tools.cc @@ -112,8 +112,7 @@ static grib_runtime_options global_options = { 0, /* skip_all */ {{0,},}, /* grib_values tolerance[MAX_KEYS] */ 0, /* infile_offset */ - 0, /* JSON output */ - 0, /* step output format */ + 0 /* JSON output */ }; static grib_handle* grib_handle_new_from_file_x(grib_context* c, FILE* f, int mode, int headers_only, int* err) @@ -362,7 +361,6 @@ static int grib_tool_without_orderby(grib_runtime_options* options) while (!options->skip_all && ((h = grib_handle_new_from_file_x(c, infile->file, options->mode, options->headers_only, &err)) != NULL || err != GRIB_SUCCESS)) { - infile->handle_count++; options->handle_count++; @@ -407,11 +405,6 @@ static int grib_tool_without_orderby(grib_runtime_options* options) continue; } - if (options->step_output_format) { - size_t step_output_format_size = strlen(options->step_output_format); - grib_set_string(h, "stepOutputFormat", options->step_output_format, &step_output_format_size); - } - if (options->format != NULL) { size_t format_len = strlen(options->format); if ((err = grib_set_string_internal(h, "formatForDoubles", options->format, &format_len)) != GRIB_SUCCESS) diff --git a/tools/grib_tools.h b/tools/grib_tools.h index 9375083d9..ef9ed42c1 100644 --- a/tools/grib_tools.h +++ b/tools/grib_tools.h @@ -16,7 +16,6 @@ #endif #include "grib_api_internal.h" -#include #include #ifndef ECCODES_ON_WINDOWS #include @@ -175,7 +174,6 @@ typedef struct grib_runtime_options grib_values tolerance[MAX_KEYS]; off_t infile_offset; int json_output; - char* step_output_format; } grib_runtime_options; extern grib_option grib_options[]; From 07e183b0e117f550b199622ac62c221a40b9ed1a Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 11 Oct 2023 11:54:12 +0000 Subject: [PATCH 065/125] ECC-1620: Remove future step format --- ...grib_accessor_class_step_human_readable.cc | 58 +++++-------------- src/step_utilities.h | 1 - 2 files changed, 16 insertions(+), 43 deletions(-) diff --git a/src/grib_accessor_class_step_human_readable.cc b/src/grib_accessor_class_step_human_readable.cc index b275c444a..557a58185 100644 --- a/src/grib_accessor_class_step_human_readable.cc +++ b/src/grib_accessor_class_step_human_readable.cc @@ -123,54 +123,28 @@ static int get_step_human_readable(grib_handle* h, char* result, size_t* length) { int err = 0; size_t slen = 2; - long step; + long step, hour, minute, second; - //size_t step_output_format_size = 128; - //char step_output_format[step_output_format_size]; - //if ((err = grib_get_string_internal(h, "step_output_format", step_output_format, &step_output_format_size)) != GRIB_SUCCESS) { - // printf("ERROR: unable to get step_output_format step_output_format=%s\n", step_output_format); - // return err; - //} - - //if (strcmp(step_output_format, "future") == 0) { - /* Change units to seconds (highest resolution) + /* Change units to seconds (highest resolution) * before computing the step value */ - // //err = grib_set_string(h, "stepUnits", "s", &slen); - // //if (err) return err; - // err = grib_get_long(h, "step", &step); - // if (err) return err; + if ((err = grib_set_string(h, "stepUnits", "s", &slen)) != GRIB_SUCCESS) + return err; + if ((err = grib_get_long(h, "step", &step)) != GRIB_SUCCESS) + return err; - // long indicator = grib_get_long(h, "indicatorOfUnitOfTimeRange", &indicator); - // auto stepOptimizer = Step(step, indicator); - // stepOptimizer.optimize_unit(); + hour = step/3600; + minute = step/60 % 60; + second = step % 60; + /* sprintf(result, "%ld:%ld:%ld", hour, minute, second); */ - // snprintf(result, 1024, "%d%s", stepOptimizer.value(), stepOptimizer.unit_as_str().c_str()); - //} - //else { - long hour, minute, second; + if (second) { + snprintf(result, 1024, "%ldh %ldm %lds", hour, minute, second); + } else { + if (minute) snprintf(result, 1024, "%ldh %ldm", hour, minute); + else snprintf(result, 1024, "%ldh", hour); + } - /* Change units to seconds (highest resolution) - * before computing the step value - */ - err = grib_set_string(h, "stepUnits", "s", &slen); - if (err) return err; - err = grib_get_long(h, "step", &step); - if (err) return err; - - hour = step/3600; - minute = step/60 % 60; - second = step % 60; - /* sprintf(result, "%ld:%ld:%ld", hour, minute, second); */ - - if (second) { - snprintf(result, 1024, "%ldh %ldm %lds", hour, minute, second); - } else { - if (minute) snprintf(result, 1024, "%ldh %ldm", hour, minute); - else snprintf(result, 1024, "%ldh", hour); - } - - //} *length = strlen(result); return GRIB_SUCCESS; } diff --git a/src/step_utilities.h b/src/step_utilities.h index eac3b2619..8224a3a32 100644 --- a/src/step_utilities.h +++ b/src/step_utilities.h @@ -15,5 +15,4 @@ #include std::optional get_step(grib_handle* h, const char* value_key, const char* unit_key); -bool is_future_output_enabled(grib_handle* h); int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step); From 5048933904ffe4976ec33af2c6b63da2ef748a37 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 11 Oct 2023 11:56:50 +0000 Subject: [PATCH 066/125] ECC-1620: Clean up set_step() --- src/step_utilities.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/step_utilities.cc b/src/step_utilities.cc index d6f244acd..dcf0d3dd5 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -32,11 +32,9 @@ std::optional get_step(grib_handle* h, const char* value_key, const char* int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step) { int err; - Step step_copy = step.copy(); - //step_copy.optimize_unit(); - if ((err = grib_set_long_internal(h, value_key.c_str(), step_copy.value())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(h, value_key.c_str(), step.value())) != GRIB_SUCCESS) return err; - if ((err = grib_set_long_internal(h, unit_key.c_str(), step_copy.unit().value())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(h, unit_key.c_str(), step.unit().value())) != GRIB_SUCCESS) return err; return GRIB_SUCCESS; } From c52c05944cfb9d7306b8be634b591138a071ca64 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 11 Oct 2023 12:47:24 +0000 Subject: [PATCH 067/125] ECC-1620: Cleanup stepOutputFormat and forceStepUnits --- definitions/grib2/boot.def | 2 -- 1 file changed, 2 deletions(-) diff --git a/definitions/grib2/boot.def b/definitions/grib2/boot.def index 85e3d80e5..2d5c2bc03 100644 --- a/definitions/grib2/boot.def +++ b/definitions/grib2/boot.def @@ -17,8 +17,6 @@ constant million = 1000000 : hidden; constant grib2divider = 1000000; alias extraDimensionPresent=zero; transient angleSubdivisions=grib2divider; # micro degrees -transient stepOutputFormat="default" : hidden; -transient forceStepUnits = 0 : hidden; meta gts_header gts_header() : no_copy,hidden,read_only; meta gts_TTAAii gts_header(20,6) : no_copy,hidden,read_only; From 06b5604692fb0d41326477f58b538f28aca00d73 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 11 Oct 2023 14:56:44 +0000 Subject: [PATCH 068/125] ECC-1620: fix grib2/boot.def --- definitions/grib2/boot.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/definitions/grib2/boot.def b/definitions/grib2/boot.def index 2d5c2bc03..f3930ea83 100644 --- a/definitions/grib2/boot.def +++ b/definitions/grib2/boot.def @@ -17,6 +17,7 @@ constant million = 1000000 : hidden; constant grib2divider = 1000000; alias extraDimensionPresent=zero; transient angleSubdivisions=grib2divider; # micro degrees +transient forceStepUnits = 255 : hidden; meta gts_header gts_header() : no_copy,hidden,read_only; meta gts_TTAAii gts_header(20,6) : no_copy,hidden,read_only; @@ -40,4 +41,3 @@ template core "grib2/sections.def"; #} template section_8 "grib2/section.8.def"; -transient forceStepUnits = 255 : hidden; From 453207593cff5f1eb1d64ff090ad62eeb6caab23 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Thu, 12 Oct 2023 13:33:09 +0100 Subject: [PATCH 069/125] Testing: Delete temp files --- tests/grib_ecc-1620.sh | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 5ca007453..d7a77d65d 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -44,8 +44,6 @@ label="grib_ecc-1620" temp=temp.$label temp2=temp_2.$label - - #### CHECK: check optimal units are set correctly in GRIB files fn="${data_dir}/reduced_gaussian_sub_area.grib2" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" @@ -58,7 +56,6 @@ grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" #${tools_dir}/grib_set -s startStep:i=60,endStep:i=180,stepUnits:s=s $temp $temp2 #grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" - ${tools_dir}/grib_set -s stepUnits:i=13,startStep:i=60,endStep:i=180 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" ${tools_dir}/grib_set -s stepUnits:s=s,startStep:i=60,endStep:i=180 $temp $temp2 @@ -74,7 +71,6 @@ grib_check_key_equals $temp2 "-p $low_level_keys" "60 h 120 h" ${tools_dir}/grib_set -s stepUnits:s=h,startStep:i=60,endStep:i=180 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "60 h 120 h" - #fn="${data_dir}/reduced_gaussian_sub_area.grib2" #low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" ##high_level_keys="startStep:s,endStep:s" @@ -94,7 +90,6 @@ grib_check_key_equals $temp2 "-p $low_level_keys" "60 h 120 h" #grib_check_key_equals $temp2 "-p $high_level_keys" "24 48" #exit - #### CHECK: grib_set - endStep + stepUnits fn="${data_dir}/reduced_gaussian_sub_area.grib2" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" @@ -158,8 +153,6 @@ ${tools_dir}/grib_set -s stepRange:s=62D-122D $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "1488 h 1440 h" grib_check_key_equals $temp2 "-p stepRange:s" "1488-2928" - - fn="${data_dir}/reduced_gaussian_surface.grib2" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s" keys__="step,stepUnits:s" @@ -167,7 +160,6 @@ keys_s="step:s" keys_i="step:i,stepUnits:s" keys_d="step:d,stepUnits:s" - ${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "3540 s" grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "59 m" @@ -192,7 +184,6 @@ grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "0 m" grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0 h" - fn="${data_dir}/reduced_gaussian_surface.grib2" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s" keys__="step,stepUnits:s" @@ -200,7 +191,6 @@ keys_s="step:s,stepUnits:s" keys_i="step:i,stepUnits:s" keys_d="step:d,stepUnits:s" - ${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 m" @@ -260,8 +250,6 @@ grib_check_key_equals $temp "-p $keys_i" "24 h" grib_check_key_equals $temp "-p $keys_d" "24 h" - - fn="${data_dir}/reduced_gaussian_sub_area.grib2" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" ${tools_dir}/grib_set -s stepRange=60m-2h $fn $temp @@ -333,10 +321,7 @@ grib_check_key_equals $temp "-p $keys_s" "18-24 18 24" grib_check_key_equals $temp "-p $keys_i" "24 18 24" grib_check_key_equals $temp "-p $keys_d" "24 18 24" -rm -f $temp +rm -f $temp $temp2 #~/build/eccodes/bin/grib_ls -m /perm/maro/referenceGRIBfiles4MTG2testing/grib1+2_operational_and_rd/151145_s2_enfo_cf_o2d_zos_2002_prod_ecmf_glob.grib2 #~/build/eccodes/bin/grib_ls -m /perm/maro/referenceGRIBfiles4MTG2testing/grib1+2_operational_and_rd/240023_ce_efas_fc_sfc_dis06_2022_0001_ecmf_lisflood.grib2 - - - From 338d20e893ecd52685f5ddab6ac2657deafd8338 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Thu, 12 Oct 2023 13:50:43 +0100 Subject: [PATCH 070/125] Cleanup --- src/grib_accessor_classes_hash.cc | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/grib_accessor_classes_hash.cc b/src/grib_accessor_classes_hash.cc index d5ff3f491..cb9a8b437 100644 --- a/src/grib_accessor_classes_hash.cc +++ b/src/grib_accessor_classes_hash.cc @@ -51,8 +51,7 @@ 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 (const char *str, size_t len) { static const unsigned short asso_values[] = { @@ -621,20 +620,19 @@ static const struct accessor_class_hash classes[] = {"g1verificationdate", &grib_accessor_class_g1verificationdate} }; -const struct accessor_class_hash * -grib_accessor_classes_hash (const char *str, size_t len) +static const struct accessor_class_hash* grib_accessor_classes_hash(const char *str, size_t len) { - if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + unsigned int key = grib_accessor_classes_get_id (str, len); + +#ifdef DEBUG { - unsigned int key = grib_accessor_classes_get_id (str, len); - - if (key <= MAX_HASH_VALUE) - { - const char *s = classes[key].name; - - if (*str == *s && !strcmp (str + 1, s + 1)) - return &classes[key]; - } + 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 ); } - return 0; +#endif + + return &classes[key]; } From 9215c5ed66c6670673f35988a01b1ecb8c1ab9ca Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 12 Oct 2023 19:39:04 +0000 Subject: [PATCH 071/125] ECC-1620: Better error message for bad units --- src/grib_accessor_class_g2step_range.cc | 41 ++----------------- src/grib_accessor_class_optimal_step_units.cc | 28 ++++++++++++- src/step.cc | 14 ++----- src/step_unit.cc | 3 +- src/step_unit.h | 34 +++++++++++++-- 5 files changed, 66 insertions(+), 54 deletions(-) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 5d09ae740..96cb3d50c 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -187,45 +187,17 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return GRIB_SUCCESS; } - -//static int pack_string_old(grib_accessor* a, const char* 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; - -// std::vector steps = parse_range(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) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); -// if ((ret = grib_set_long_internal(h, "stepUnits", step_0.unit().to_long()))) -// return ret; -// } - -// if ((ret = grib_set_long_internal(h, self->start_step, step_0.value()))) -// return ret; - -// if ((self->end_step != NULL) && (steps.size() > 1)) { -// if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) -// return ret; -// } -// return GRIB_SUCCESS; -//} - - -static int pack_string_new(grib_accessor* a, const char* val, size_t* len) +static int pack_string(grib_accessor* a, const char* 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; std::vector steps = parse_range(val); - if (steps.size() == 0) + if (steps.size() == 0) { + grib_context_log(a->context, GRIB_LOG_ERROR, "Could not parse step range: %s", val); return GRIB_INVALID_ARGUMENT; + } Step step_0 = steps[0]; Step step_1; @@ -247,11 +219,6 @@ static int pack_string_new(grib_accessor* a, const char* val, size_t* len) return GRIB_SUCCESS; } -static int pack_string(grib_accessor* a, const char* val, size_t* len) -{ - return pack_string_new(a, val, len); -} - static int value_count(grib_accessor* a, long* count) { *count = 1; diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 7a9316952..29017fc62 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -148,6 +148,21 @@ static long staticForceStepUnits = Unit{Unit::Value::MISSING}.value(); static int pack_long(grib_accessor* a, const long* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); + try { + if (!Unit::is_visible(Unit{*val})) + throw std::runtime_error("Unit masked"); + } + catch (std::exception& e) { + auto visible_units = Unit::list_visible_units(); + std::string visible_units_str; + for (auto& u : visible_units) + visible_units_str += Unit{u}.value() + ","; + visible_units_str.pop_back(); + + std::string msg = std::string{"Invalid unit: "} + std::to_string(*val) + " (" + e.what() + ")" + ". Available units are: " + visible_units_str; + grib_context_log(a->context, GRIB_LOG_ERROR, msg.c_str()); + return GRIB_INVALID_ARGUMENT; + } int ret; staticStepUnits = *val; @@ -192,10 +207,21 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) { try { long unit = Unit{val}.value(); + + if (!Unit::is_visible(Unit{val})) + throw std::runtime_error("Unit masked"); + pack_long(a, &unit, len); } catch (std::exception& e) { - grib_context_log(a->context, GRIB_LOG_ERROR, "Invalid unit: %s", val); + auto visible_units = Unit::list_visible_units(); + std::string visible_units_str; + for (auto& u : visible_units) + visible_units_str += Unit{u}.value() + ","; + visible_units_str.pop_back(); + + std::string msg = "Invalid unit: " + std::string(val) + " (" + e.what() + ")" + ". Available units are: " + visible_units_str; + grib_context_log(a->context, GRIB_LOG_ERROR, msg.c_str()); return GRIB_INVALID_ARGUMENT; } return GRIB_SUCCESS; diff --git a/src/step.cc b/src/step.cc index 629143c34..ac7b3bed3 100644 --- a/src/step.cc +++ b/src/step.cc @@ -114,11 +114,11 @@ std::pair find_common_units(const Step& startStep, const Step& endSt b.recalculateValue(); } else { - auto it = std::find_if(Unit::unit_order_.begin(), Unit::unit_order_.end(), [&](const auto& e) { + auto it = std::find_if(Unit::publicly_visible_units_.begin(), Unit::publicly_visible_units_.end(), [&](const auto& e) { return e == a.unit().value() || e == b.unit().value(); }); - assert(it != Unit::unit_order_.end()); + assert(it != Unit::publicly_visible_units_.end()); a.set_unit(*it); b.set_unit(*it); @@ -165,7 +165,7 @@ Step& Step::optimize_unit() unit_ = internal_unit_; Seconds seconds = to_seconds(internal_value_, internal_unit_); - for (auto it = Unit::unit_order_.rbegin(); it != Unit::unit_order_.rend(); ++it) { + for (auto it = Unit::publicly_visible_units_.rbegin(); it != Unit::publicly_visible_units_.rend(); ++it) { long multiplier = Unit::get_converter().unit_to_duration(*it); if (seconds.count() % multiplier == 0) { internal_value_ = seconds.count() / multiplier; @@ -178,14 +178,6 @@ Step& Step::optimize_unit() return *this; } -//Step Step::copy() const { -// Step ret{}; -// ret.internal_value_ = internal_value_; -// ret.internal_unit_ = internal_unit_; -// ret.unit_ = unit_; -// return ret; -//} - template <> std::string Step::value(const std::string& format) const { constexpr int max_size = 128; diff --git a/src/step_unit.cc b/src/step_unit.cc index 4fb323586..54db81487 100644 --- a/src/step_unit.cc +++ b/src/step_unit.cc @@ -12,11 +12,10 @@ Unit::Map Unit::map_{}; -std::vector Unit::unit_order_ = { +std::vector Unit::publicly_visible_units_ = { Unit::Value::SECOND, Unit::Value::MINUTE, Unit::Value::HOUR, - //Unit::Value::DAY, }; std::vector Unit::complete_unit_order_ = { diff --git a/src/step_unit.h b/src/step_unit.h index bffb67715..778e17fed 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -16,6 +16,7 @@ #include #include #include +#include template using Minutes = std::chrono::duration>; template using Hours = std::chrono::duration>; @@ -60,9 +61,24 @@ public: }; Unit() : internal_value_(Value::HOUR) {} + explicit Unit(Value unit_value) : internal_value_(unit_value) {} - explicit Unit(const std::string& unit_value) {internal_value_ = map_.name_to_unit(unit_value);} - explicit Unit(long unit_value) {internal_value_ = map_.long_to_unit(unit_value);} + + explicit Unit(const std::string& unit_value) { + try { + internal_value_ = map_.name_to_unit(unit_value); + } catch (std::exception& e) { + throw std::runtime_error(std::string{"Unit not found"}); + } + } + + explicit Unit(long unit_value) { + try { + internal_value_ = map_.long_to_unit(unit_value); + } catch (std::exception& e) { + throw std::runtime_error(std::string{"Unit not found"}); + } + } bool operator>(const Unit& other) const {return map_.unit_to_duration(internal_value_) > map_.unit_to_duration(other.internal_value_);} bool operator==(const Value value) const {return map_.unit_to_duration(internal_value_) == map_.unit_to_duration(value);} @@ -75,8 +91,20 @@ public: return *this; } + static bool is_visible(Unit unit) { + return std::find(publicly_visible_units_.begin(), publicly_visible_units_.end(), unit.internal_value_) != publicly_visible_units_.end(); + } + + static std::vector list_visible_units() { + std::vector result; + for (const auto& value : publicly_visible_units_) { + result.push_back(Unit(value)); + } + return result; + } + template T value() const; - static std::vector unit_order_; + static std::vector publicly_visible_units_; static std::vector complete_unit_order_; private: From e0cd0dc7930b41e183868742486576d0e6a7f971 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 12 Oct 2023 22:13:44 +0000 Subject: [PATCH 072/125] ECC-1620: Restore test --- tests/grib_step.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/grib_step.sh b/tests/grib_step.sh index a2e41636f..2b1ca37b6 100755 --- a/tests/grib_step.sh +++ b/tests/grib_step.sh @@ -137,9 +137,8 @@ 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 -# 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" +${tools_dir}/grib_set -s stepRange:d=14.56 $grib2_sample $temp +grib_check_key_equals $temp "stepRange,startStep,endStep" "14 14 14" # Key validityDateTime # ----------------------------------------------- From d21f76ced7beaffef500b53c052ab5a807ff5f90 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 12 Oct 2023 22:23:17 +0000 Subject: [PATCH 073/125] ECC-1620: Grep for whole error message --- tests/grib_set.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/grib_set.sh b/tests/grib_set.sh index 0489c61c3..26cec498b 100755 --- a/tests/grib_set.sh +++ b/tests/grib_set.sh @@ -223,8 +223,7 @@ ${tools_dir}/grib_set -s stepUnits=d $input $outfile > $temp 2>&1 status=$? set -e [ $status -ne 0 ] -grep -q "Invalid argument" $temp -#grep -q "stepUnits: No such code table entry.*Did you mean" $temp +grep -q "Invalid unit:.*(Unit not found). Available units are:.*" $temp # ------------------------ # Unreadable message From e1fff76338b206f9beb9981cfab2737ffee44e26 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 13 Oct 2023 11:56:56 +0000 Subject: [PATCH 074/125] ECC-1620: Remove formatForDoubles --- tools/grib_tools.cc | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tools/grib_tools.cc b/tools/grib_tools.cc index fc5637ab6..9c5663a00 100644 --- a/tools/grib_tools.cc +++ b/tools/grib_tools.cc @@ -405,19 +405,6 @@ static int grib_tool_without_orderby(grib_runtime_options* options) continue; } - if (options->format != NULL) { - size_t format_len = strlen(options->format); - if ((err = grib_set_string_internal(h, "formatForDoubles", options->format, &format_len)) != GRIB_SUCCESS) - return err; - } - else { - char format[1024]; - size_t format_len = sizeof(format); - if ((err = grib_get_string_internal(h, "formatForDoubles", format, &format_len)) != GRIB_SUCCESS) - return err; - options->format = strdup(format); - } - grib_tool_new_handle_action(options, h); grib_print_key_values(options, h); From bd8ee44ab4a9f8a0b1b363e1ff8f03de50122a6f Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 16 Oct 2023 09:04:58 +0000 Subject: [PATCH 075/125] ECC-1620: Test negative forecastTime with sub-hourly units --- tests/grib_ecc-1620.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index d7a77d65d..fb539b7d8 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -43,6 +43,19 @@ grib_check_key_equals() label="grib_ecc-1620" temp=temp.$label temp2=temp_2.$label +samples_dir=$ECCODES_SAMPLES_PATH + + +#### CHECK negative forecastTime +fn="${data_dir}/reduced_gaussian_sub_area.grib2" +low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" +${tools_dir}/grib_set -s forecastTime=-6,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=6,indicatorOfUnitForTimeRange=h $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "-6 h 6 h" + +grib_check_key_equals $temp "-s stepUnits:s=h -p startStep:s,endStep:s" "-6 0" +grib_check_key_equals $temp "-s stepUnits:s=m -p startStep:s,endStep:s" "-360m 0m" +grib_check_key_equals $temp "-s stepUnits:s=s -p startStep:s,endStep:s" "-21600s 0s" + #### CHECK: check optimal units are set correctly in GRIB files fn="${data_dir}/reduced_gaussian_sub_area.grib2" From b077cdbb856cc8f14a7a9d3ba52cf11c84f54def Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Mon, 16 Oct 2023 15:28:14 +0100 Subject: [PATCH 076/125] Cleanup --- src/grib_accessor_class_g2end_step.cc | 16 ---------------- src/grib_accessor_class_step_in_units.cc | 8 +------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index a8d1a4968..cfa8500b6 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -178,13 +178,11 @@ static void init(grib_accessor* a, const long l, grib_arguments* c) self->numberOfTimeRange = grib_arguments_get_name(h, c, n++); } - static void dump(grib_accessor* a, grib_dumper* dumper) { grib_dump_double(dumper, a, NULL); } - // See GRIB-488 static bool is_special_expver(const grib_handle* h) { @@ -205,7 +203,6 @@ static bool is_special_expver(const grib_handle* h) return false; } - static int convert_time_range_long_( grib_handle* h, long stepUnits, /* step_units */ @@ -227,7 +224,6 @@ static int convert_time_range_long_( return GRIB_SUCCESS; } - static int unpack_one_time_range_long_(grib_accessor* a, long* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; @@ -273,7 +269,6 @@ static int unpack_one_time_range_long_(grib_accessor* a, long* val, size_t* len) return GRIB_SUCCESS; } - static int unpack_one_time_range_double_(grib_accessor* a, double *val , size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; @@ -322,7 +317,6 @@ static int unpack_one_time_range_double_(grib_accessor* a, double *val , size_t* return GRIB_SUCCESS; } - #define MAX_NUM_TIME_RANGES 16 /* maximum number of time range specifications */ static int unpack_multiple_time_ranges_long_(grib_accessor* a, long* val, size_t* len) { @@ -377,8 +371,6 @@ static int unpack_multiple_time_ranges_long_(grib_accessor* a, long* val, size_t return GRIB_DECODING_ERROR; } - - static int unpack_multiple_time_ranges_double_(grib_accessor* a, double* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; @@ -439,7 +431,6 @@ static int unpack_multiple_time_ranges_double_(grib_accessor* a, double* val, si return GRIB_DECODING_ERROR; } - // For the old implementation of unpack_long, see // src/deprecated/grib_accessor_class_g2end_step.unpack_long.cc // @@ -477,7 +468,6 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) return GRIB_SUCCESS; } - static int unpack_double(grib_accessor* a, double* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; @@ -512,8 +502,6 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) return GRIB_SUCCESS; } - - static int pack_long_(grib_accessor* a, const long end_step_value, const long end_step_unit) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; @@ -628,8 +616,6 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en return GRIB_SUCCESS; } - - static int unpack_string(grib_accessor* a, char* val, size_t* len) { grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a; @@ -667,7 +653,6 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return GRIB_SUCCESS; } - static int pack_long(grib_accessor* a, const long* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); @@ -692,7 +677,6 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return pack_long_(a, *val, end_step_unit); } - static int pack_string(grib_accessor* a, const char* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 02641d714..1262ac5e3 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -135,7 +135,6 @@ static void dump(grib_accessor* a, grib_dumper* dumper) grib_dump_double(dumper, a, NULL); } - static int unpack_long(grib_accessor* a, long* val, size_t* len) { grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; @@ -161,8 +160,6 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) 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; @@ -187,8 +184,7 @@ static int unpack_double(grib_accessor* a, double * val, size_t* len) return GRIB_SUCCESS; } - -int pack_long_new_(grib_accessor* a, const long start_step_value, const long start_step_unit) { +static int pack_long_new_(grib_accessor* a, const long start_step_value, const long start_step_unit) { grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); int err = 0; @@ -234,7 +230,6 @@ int pack_long_new_(grib_accessor* a, const long start_step_value, const long sta return GRIB_SUCCESS; } - static int pack_long(grib_accessor* a, const long* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); @@ -261,7 +256,6 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return ret; } - static int pack_string(grib_accessor* a, const char* val, size_t* len) { int ret = 0; From e342186550a65aa6bed63f3ce3e06e00108ebffa Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Mon, 16 Oct 2023 15:31:23 +0100 Subject: [PATCH 077/125] Cleanup --- src/grib_accessor_class_optimal_step_units.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 29017fc62..3461d85e8 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -8,10 +8,6 @@ * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. */ -/********************************************* - * Enrico Fucile - *******************************************/ - #include "grib_api_internal.h" #include "step.h" #include "step_utilities.h" @@ -136,7 +132,6 @@ static void dump(grib_accessor* a, grib_dumper* dumper) grib_dump_string(dumper, a, NULL); } - static size_t string_length(grib_accessor* a) { return 255; @@ -147,7 +142,7 @@ static long staticForceStepUnits = Unit{Unit::Value::MISSING}.value(); static int pack_long(grib_accessor* a, const long* val, size_t* len) { - grib_handle* h = grib_handle_of_accessor(a); + grib_handle* h = grib_handle_of_accessor(a); try { if (!Unit::is_visible(Unit{*val})) throw std::runtime_error("Unit masked"); From 8bda848b382dcdabd3b34c5eeab8d57a9b13df8e Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Mon, 16 Oct 2023 15:34:58 +0100 Subject: [PATCH 078/125] Cleanup --- src/grib_accessor_class_step_in_units.cc | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 1262ac5e3..1a9a92e70 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -121,7 +121,7 @@ grib_accessor_class* grib_accessor_class_step_in_units = &_grib_accessor_class_s static void init(grib_accessor* a, const long l, grib_arguments* c) { grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; - int n = 0; + int n = 0; self->forecast_time_value = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); self->forecast_time_unit = grib_arguments_get_name(grib_handle_of_accessor(a), c, n++); @@ -138,7 +138,7 @@ static void dump(grib_accessor* a, grib_dumper* dumper) 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; + int err = 0; long forecast_time_value, forecast_time_unit, step_units; grib_handle* h = grib_handle_of_accessor(a); @@ -163,7 +163,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) static int unpack_double(grib_accessor* a, double * val, size_t* len) { grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; - int err = 0; + int err = 0; long forecast_time_value, forecast_time_unit, step_units; grib_handle* h = grib_handle_of_accessor(a); @@ -184,10 +184,11 @@ static int unpack_double(grib_accessor* a, double * val, size_t* len) return GRIB_SUCCESS; } -static int pack_long_new_(grib_accessor* a, const long start_step_value, const long start_step_unit) { +static int pack_long_new_(grib_accessor* a, const long start_step_value, const long start_step_unit) +{ grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; - grib_handle* h = grib_handle_of_accessor(a); - int err = 0; + grib_handle* h = grib_handle_of_accessor(a); + int err = 0; long forecast_time_unit; long start_step_value_old; long start_step_unit_old; @@ -232,8 +233,8 @@ static int pack_long_new_(grib_accessor* a, const long start_step_value, const l static int pack_long(grib_accessor* a, const long* val, size_t* len) { - grib_handle* h = grib_handle_of_accessor(a); - int ret; + grib_handle* h = grib_handle_of_accessor(a); + int ret = GRIB_SUCCESS; long force_step_units; if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) @@ -258,7 +259,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { - int ret = 0; + int ret = GRIB_SUCCESS; Step step = step_from_string(val); if ((ret = pack_long_new_(a, step.value(), step.unit().value())) != GRIB_SUCCESS) @@ -271,7 +272,7 @@ 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; + int ret = GRIB_SUCCESS; long start_step_value; long start_step_unit; long step_units; From 12f1612647900bd6c9958a9352927b1ef93b5c9c Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 18 Oct 2023 08:22:46 +0000 Subject: [PATCH 079/125] ECC-1620: Remove restriction in stepUnits --- src/grib_accessor_class_optimal_step_units.cc | 38 +++++++++---------- src/step_unit.h | 22 +++++------ 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 29017fc62..a29dfdf75 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -147,19 +147,22 @@ static long staticForceStepUnits = Unit{Unit::Value::MISSING}.value(); static int pack_long(grib_accessor* a, const long* val, size_t* len) { - grib_handle* h = grib_handle_of_accessor(a); + grib_handle* h = grib_handle_of_accessor(a); + auto supported_units = Unit::list_supported_units(); try { - if (!Unit::is_visible(Unit{*val})) - throw std::runtime_error("Unit masked"); + Unit unit{*val}; // throws if not supported + auto iter = std::find(supported_units.begin(), supported_units.end(), unit); + if (iter == supported_units.end()) { + throw std::runtime_error{"Unit not supported"}; + } } catch (std::exception& e) { - auto visible_units = Unit::list_visible_units(); - std::string visible_units_str; - for (auto& u : visible_units) - visible_units_str += Unit{u}.value() + ","; - visible_units_str.pop_back(); + std::string supported_units_str; + for (auto& u : supported_units) + supported_units_str += Unit{u}.value() + ","; + supported_units_str.pop_back(); - std::string msg = std::string{"Invalid unit: "} + std::to_string(*val) + " (" + e.what() + ")" + ". Available units are: " + visible_units_str; + std::string msg = std::string{"Invalid unit: "} + std::to_string(*val) + " (" + e.what() + ")" + ". Available X tunits are: " + supported_units_str; grib_context_log(a->context, GRIB_LOG_ERROR, msg.c_str()); return GRIB_INVALID_ARGUMENT; } @@ -207,23 +210,20 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) { try { long unit = Unit{val}.value(); - - if (!Unit::is_visible(Unit{val})) - throw std::runtime_error("Unit masked"); - pack_long(a, &unit, len); } catch (std::exception& e) { - auto visible_units = Unit::list_visible_units(); - std::string visible_units_str; - for (auto& u : visible_units) - visible_units_str += Unit{u}.value() + ","; - visible_units_str.pop_back(); + auto supported_units = Unit::list_supported_units(); + std::string supported_units_str; + for (auto& u : supported_units) + supported_units_str += Unit{u}.value() + ","; + supported_units_str.pop_back(); - std::string msg = "Invalid unit: " + std::string(val) + " (" + e.what() + ")" + ". Available units are: " + visible_units_str; + std::string msg = "Invalid unit: " + std::string(val) + " (" + e.what() + ")" + ". Available units are: " + supported_units_str; grib_context_log(a->context, GRIB_LOG_ERROR, msg.c_str()); return GRIB_INVALID_ARGUMENT; } + return GRIB_SUCCESS; } diff --git a/src/step_unit.h b/src/step_unit.h index 778e17fed..7dc7eeb33 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -91,22 +91,22 @@ public: return *this; } - static bool is_visible(Unit unit) { - return std::find(publicly_visible_units_.begin(), publicly_visible_units_.end(), unit.internal_value_) != publicly_visible_units_.end(); - } - - static std::vector list_visible_units() { - std::vector result; - for (const auto& value : publicly_visible_units_) { - result.push_back(Unit(value)); - } - return result; - } template T value() const; static std::vector publicly_visible_units_; static std::vector complete_unit_order_; + static std::vector list_supported_units() { + std::vector result; + for (const auto& value : complete_unit_order_) { + if (value == Value::MISSING) + continue; + result.push_back(Unit(value)); + } + + return result; + } + private: class Map { public: From e7edaa21364311c84b9176d1fb86570c3d287fe8 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 18 Oct 2023 08:43:30 +0000 Subject: [PATCH 080/125] ECC-1620: Catch exceptions --- src/grib_accessor_class_g2end_step.cc | 104 ++++++---- src/grib_accessor_class_g2step_range.cc | 178 ++++++++++-------- src/grib_accessor_class_optimal_step_units.cc | 44 +++-- src/grib_accessor_class_step_in_units.cc | 84 ++++++--- 4 files changed, 250 insertions(+), 160 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index cfa8500b6..bb398e5ea 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -456,13 +456,19 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) return ret; Assert(numberOfTimeRange == 1 || numberOfTimeRange == 2); - if (numberOfTimeRange == 1) { - ret = unpack_one_time_range_long_(a, val, len); - return ret; + try { + if (numberOfTimeRange == 1) { + ret = unpack_one_time_range_long_(a, val, len); + return ret; + } + else { + ret = unpack_multiple_time_ranges_long_(a, val, len); + return ret; + } } - else { - ret = unpack_multiple_time_ranges_long_(a, val, len); - return ret; + catch (std::exception& e) { + grib_context_log(h->context, GRIB_LOG_ERROR, "grib_accessor_g2end_step::unpack_long: %s", e.what()); + return GRIB_DECODING_ERROR; } return GRIB_SUCCESS; @@ -490,13 +496,19 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) return ret; Assert(numberOfTimeRange == 1 || numberOfTimeRange == 2); - if (numberOfTimeRange == 1) { - ret = unpack_one_time_range_double_(a, val, len); - return ret; + try { + if (numberOfTimeRange == 1) { + ret = unpack_one_time_range_double_(a, val, len); + return ret; + } + else { + ret = unpack_multiple_time_ranges_double_(a, val, len); + return ret; + } } - else { - ret = unpack_multiple_time_ranges_double_(a, val, len); - return ret; + catch (std::exception& e) { + grib_context_log(h->context, GRIB_LOG_ERROR, "grib_accessor_g2end_step::unpack_double: %s", e.what()); + return GRIB_DECODING_ERROR; } return GRIB_SUCCESS; @@ -634,21 +646,27 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) if ((ret = grib_get_string(h, "formatForDoubles", fp_format, &fp_format_len)) != GRIB_SUCCESS) return ret; - Step step(step_value, step_units); - step.set_unit(step_units); + try { + Step step(step_value, step_units); + step.set_unit(step_units); - std::stringstream ss; + std::stringstream ss; - ss << step.value(fp_format); + ss << step.value(fp_format); - size_t size = ss.str().size() + 1; + size_t size = ss.str().size() + 1; - if (*len < size) - return GRIB_ARRAY_TOO_SMALL; + if (*len < size) + return GRIB_ARRAY_TOO_SMALL; - *len = size; + *len = size; - memcpy(val, ss.str().c_str(), size); + memcpy(val, ss.str().c_str(), size); + } + catch (std::exception& e) { + grib_context_log(h->context, GRIB_LOG_ERROR, "grib_accessor_g2end_step::unpack_string: %s", e.what()); + return GRIB_DECODING_ERROR; + } return GRIB_SUCCESS; } @@ -662,32 +680,44 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) return ret; - long end_step_unit; - if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { - if ((ret = grib_get_long_internal(h, "endStepUnit", &end_step_unit)) != GRIB_SUCCESS) - return ret; + try { + long end_step_unit; + if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { + if ((ret = grib_get_long_internal(h, "endStepUnit", &end_step_unit)) != GRIB_SUCCESS) + return ret; - if (Unit{end_step_unit} == Unit{Unit::Value::MISSING}) - end_step_unit = Unit{Unit::Value::HOUR}.value(); + if (Unit{end_step_unit} == Unit{Unit::Value::MISSING}) + end_step_unit = Unit{Unit::Value::HOUR}.value(); + } + else { + end_step_unit = force_step_units; + } + ret = pack_long_(a, *val, end_step_unit); } - else { - end_step_unit = force_step_units; + catch (std::exception& e) { + grib_context_log(h->context, GRIB_LOG_ERROR, "grib_accessor_g2end_step::pack_long: %s", e.what()); + return GRIB_DECODING_ERROR; } - - return pack_long_(a, *val, end_step_unit); + return ret; } static int pack_string(grib_accessor* a, const char* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - Step end_step = step_from_string(val); - end_step.optimize_unit(); + try { + Step end_step = step_from_string(val); + end_step.optimize_unit(); - if ((ret = grib_set_long_internal(h, "endStepUnit", end_step.unit().value())) != GRIB_SUCCESS) - return ret; + if ((ret = grib_set_long_internal(h, "endStepUnit", end_step.unit().value())) != GRIB_SUCCESS) + return ret; - if ((ret = pack_long_(a, end_step.value(), end_step.unit().value())) != GRIB_SUCCESS) - return ret; + if ((ret = pack_long_(a, end_step.value(), end_step.unit().value())) != GRIB_SUCCESS) + return ret; + } + catch (std::exception& e) { + grib_context_log(h->context, GRIB_LOG_ERROR, "grib_accessor_g2end_step::pack_string: %s", e.what()); + return GRIB_DECODING_ERROR; + } return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 96cb3d50c..d93358a94 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -146,43 +146,49 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; if ((ret= grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; - if (Unit{step_units} == Unit{Unit::Value::MISSING}) { - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + try { + if (Unit{step_units} == Unit{Unit::Value::MISSING}) { + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + return ret; + } + + char fp_format[128] = "%g"; + size_t fp_format_len = sizeof(fp_format); + if ((ret = grib_get_string_internal(h, "formatForDoubles", fp_format, &fp_format_len)) != GRIB_SUCCESS) return ret; - } + std::stringstream ss; - char fp_format[128] = "%g"; - size_t fp_format_len = sizeof(fp_format); - if ((ret = grib_get_string_internal(h, "formatForDoubles", fp_format, &fp_format_len)) != GRIB_SUCCESS) - return ret; - std::stringstream ss; - - Step start_step{start_step_value, step_units}; - if (self->end_step == NULL) { - ss << start_step.value(fp_format); - } - else { - if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) - return ret; - - Step end_step{end_step_value, step_units}; - - if (start_step_value == end_step_value) { - ss << end_step.value(fp_format); + Step start_step{start_step_value, step_units}; + if (self->end_step == NULL) { + ss << start_step.value(fp_format); } else { - ss << start_step.value(fp_format) << "-" << end_step.value(fp_format); + if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) + return ret; + + Step end_step{end_step_value, step_units}; + + if (start_step_value == end_step_value) { + ss << end_step.value(fp_format); + } + else { + ss << start_step.value(fp_format) << "-" << end_step.value(fp_format); + } } + + size = ss.str().size() + 1; + + if (*len < size) + return GRIB_ARRAY_TOO_SMALL; + + *len = size; + + memcpy(val, ss.str().c_str(), size); + } + catch (std::exception& e) { + grib_context_log(a->context, GRIB_LOG_ERROR, "grib_accessor_g2step_range::unpack_string: %s", e.what()); + return GRIB_DECODING_ERROR; } - - size = ss.str().size() + 1; - - if (*len < size) - return GRIB_ARRAY_TOO_SMALL; - - *len = size; - - memcpy(val, ss.str().c_str(), size); return GRIB_SUCCESS; } @@ -193,29 +199,35 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int ret = 0; - std::vector steps = parse_range(val); - if (steps.size() == 0) { - grib_context_log(a->context, GRIB_LOG_ERROR, "Could not parse step range: %s", val); + try { + std::vector steps = parse_range(val); + if (steps.size() == 0) { + grib_context_log(a->context, GRIB_LOG_ERROR, "Could not parse step range: %s", val); + return GRIB_INVALID_ARGUMENT; + } + + Step step_0 = steps[0]; + Step step_1; + if (steps.size() > 1) { + std::tie(step_0, step_1) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); + } + + if ((ret = grib_set_long_internal(h, "startStepUnit", step_0.unit().value()))) + return ret; + if ((ret = set_step(h, "forecastTime" , "indicatorOfUnitOfTimeRange", step_0)) != GRIB_SUCCESS) + return ret; + + if ((self->end_step != NULL) && (steps.size() > 1)) { + if ((ret = grib_set_long_internal(h, "endStepUnit", step_1.unit().value()))) + return ret; + if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) + return ret; + } + } + catch (std::exception& e) { + grib_context_log(a->context, GRIB_LOG_ERROR, "grib_accessor_class_g2step_range::pack_string: %s", e.what()); return GRIB_INVALID_ARGUMENT; } - - Step step_0 = steps[0]; - Step step_1; - if (steps.size() > 1) { - std::tie(step_0, step_1) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); - } - - if ((ret = grib_set_long_internal(h, "startStepUnit", step_0.unit().value()))) - return ret; - if ((ret = set_step(h, "forecastTime" , "indicatorOfUnitOfTimeRange", step_0)) != GRIB_SUCCESS) - return ret; - - if ((self->end_step != NULL) && (steps.size() > 1)) { - if ((ret = grib_set_long_internal(h, "endStepUnit", step_1.unit().value()))) - return ret; - if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) - return ret; - } return GRIB_SUCCESS; } @@ -251,22 +263,28 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) if ((ret = grib_get_long_internal(h, self->start_step, &end_start_value)) != GRIB_SUCCESS) return ret; - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) - throw std::runtime_error("Failed to get stepUnits"); - if (Unit{step_units} == Unit{Unit::Value::MISSING}) { + try { if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) - return ret; - } + throw std::runtime_error("Failed to get stepUnits"); + if (Unit{step_units} == Unit{Unit::Value::MISSING}) { + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + return ret; + } - Step start_step{end_start_value, step_units}; - if (self->end_step == NULL) { - *val = start_step.value(); + Step start_step{end_start_value, step_units}; + if (self->end_step == NULL) { + *val = start_step.value(); + } + else { + if ((ret = grib_get_long_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) + return ret; + Step end_step{end_step_value, step_units}; + *val = end_step.value(); + } } - else { - if ((ret = grib_get_long_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) - return ret; - Step end_step{end_step_value, step_units}; - *val = end_step.value(); + catch (std::exception& e) { + grib_context_log(a->context, GRIB_LOG_ERROR, "Failed to unpack step range: %s", e.what()); + return GRIB_DECODING_ERROR; } return GRIB_SUCCESS; @@ -287,20 +305,26 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) throw std::runtime_error("Failed to get stepUnits"); - if (Unit{step_units} == Unit{Unit::Value::MISSING}) { - if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) - return ret; - } + try { + if (Unit{step_units} == Unit{Unit::Value::MISSING}) { + if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) + return ret; + } - Step start_step{end_start_value, step_units}; - if (self->end_step == NULL) { - *val = start_step.value(); + Step start_step{end_start_value, step_units}; + if (self->end_step == NULL) { + *val = start_step.value(); + } + else { + if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) + return ret; + Step end_step{end_step_value, step_units}; + *val = end_step.value(); + } } - else { - if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) - return ret; - Step end_step{end_step_value, step_units}; - *val = end_step.value(); + catch (std::exception& e) { + grib_context_log(a->context, GRIB_LOG_ERROR, "grid_accessor_g2step_range::unpack_double: %s", e.what()); + return GRIB_DECODING_ERROR; } return GRIB_SUCCESS; diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 9bbca118e..362415299 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -173,29 +173,35 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) static int unpack_long(grib_accessor* a, long* val, size_t* len) { - if (Unit{staticStepUnits} != Unit{Unit::Value::MISSING}) { - *val = staticStepUnits; - return GRIB_SUCCESS; - } + try { + if (Unit{staticStepUnits} != Unit{Unit::Value::MISSING}) { + *val = staticStepUnits; + return GRIB_SUCCESS; + } - grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; - grib_handle* h = grib_handle_of_accessor(a); + grib_accessor_optimal_step_units* self = (grib_accessor_optimal_step_units*)a; + grib_handle* h = grib_handle_of_accessor(a); - auto forecast_time_opt = get_step(h, self->forecast_time_value, self->forecast_time_unit); - auto time_range_opt = get_step(h, self->time_range_value, self->time_range_unit); + auto forecast_time_opt = get_step(h, self->forecast_time_value, self->forecast_time_unit); + auto time_range_opt = get_step(h, self->time_range_value, self->time_range_unit); - if (forecast_time_opt && time_range_opt) { - auto [step_a, step_b] = find_common_units(forecast_time_opt.value().optimize_unit(), (forecast_time_opt.value() + time_range_opt.value()).optimize_unit()); - *val = step_a.unit().value(); + if (forecast_time_opt && time_range_opt) { + auto [step_a, step_b] = find_common_units(forecast_time_opt.value().optimize_unit(), (forecast_time_opt.value() + time_range_opt.value()).optimize_unit()); + *val = step_a.unit().value(); + } + else if (forecast_time_opt && !time_range_opt) { + *val = forecast_time_opt.value().optimize_unit().unit().value(); + } + else if (!forecast_time_opt && time_range_opt) { + *val = time_range_opt.value().optimize_unit().unit().value(); + } + else if (!forecast_time_opt && !time_range_opt) { + *val = Unit{Unit::Value::HOUR}.value(); + } } - else if (forecast_time_opt && !time_range_opt) { - *val = forecast_time_opt.value().optimize_unit().unit().value(); - } - else if (!forecast_time_opt && time_range_opt) { - *val = time_range_opt.value().optimize_unit().unit().value(); - } - else if (!forecast_time_opt && !time_range_opt) { - *val = Unit{Unit::Value::HOUR}.value(); + catch (std::exception& e) { + grib_context_log(a->context, GRIB_LOG_ERROR, e.what()); + return GRIB_INTERNAL_ERROR; } return GRIB_SUCCESS; diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 1a9a92e70..d88c8c62c 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -149,13 +149,19 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) if ((err = grib_get_long_internal(h, self->forecast_time_value, &forecast_time_value))) return err; - Step step{forecast_time_value, forecast_time_unit}; - step.optimize_unit(); + try { + Step step{forecast_time_value, forecast_time_unit}; + step.optimize_unit(); - if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.value())) != GRIB_SUCCESS) - return err; + if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.value())) != GRIB_SUCCESS) + return err; - *val = step.value(Unit{step_units}); + *val = step.value(Unit{step_units}); + } + catch (std::exception& e) { + grib_context_log(h->context, GRIB_LOG_ERROR, "step_in_units: %s", e.what()); + return GRIB_DECODING_ERROR; + } return GRIB_SUCCESS; } @@ -174,12 +180,18 @@ static int unpack_double(grib_accessor* a, double * val, size_t* len) if ((err = grib_get_long_internal(h, self->forecast_time_value, &forecast_time_value))) return err; - Step step{forecast_time_value, forecast_time_unit}; + try { + Step step{forecast_time_value, forecast_time_unit}; - if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.value())) != GRIB_SUCCESS) - return err; + if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.value())) != GRIB_SUCCESS) + return err; - *val = step.value(Unit{step_units}); + *val = step.value(Unit{step_units}); + } + catch (std::exception& e) { + grib_context_log(h->context, GRIB_LOG_ERROR, "step_in_units: %s", e.what()); + return GRIB_DECODING_ERROR; + } return GRIB_SUCCESS; } @@ -241,15 +253,21 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return ret; long start_step_unit; - if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { - if ((ret = grib_get_long_internal(h, "startStepUnit", &start_step_unit)) != GRIB_SUCCESS) - return ret; + try { + if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { + if ((ret = grib_get_long_internal(h, "startStepUnit", &start_step_unit)) != GRIB_SUCCESS) + return ret; - if (Unit{start_step_unit} == Unit{Unit::Value::MISSING}) - start_step_unit = Unit{Unit::Value::HOUR}.value(); + if (Unit{start_step_unit} == Unit{Unit::Value::MISSING}) + start_step_unit = Unit{Unit::Value::HOUR}.value(); + } + else { + start_step_unit = force_step_units; + } } - else { - start_step_unit = force_step_units; + catch (std::exception& e) { + grib_context_log(h->context, GRIB_LOG_ERROR, "step_in_units: %s", e.what()); + return GRIB_DECODING_ERROR; } ret = pack_long_new_(a, *val, start_step_unit); @@ -260,10 +278,16 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { int ret = GRIB_SUCCESS; - Step step = step_from_string(val); + try { + Step step = step_from_string(val); - if ((ret = pack_long_new_(a, step.value(), step.unit().value())) != GRIB_SUCCESS) - return ret; + if ((ret = pack_long_new_(a, step.value(), step.unit().value())) != GRIB_SUCCESS) + return ret; + } + catch (std::exception& e) { + grib_context_log(a->context, GRIB_LOG_ERROR, "step_in_units: %s", e.what()); + return GRIB_DECODING_ERROR; + } return GRIB_SUCCESS; } @@ -288,19 +312,25 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) if ((ret = grib_get_string_internal(h, "formatForDoubles", fp_format, &fp_format_len)) != GRIB_SUCCESS) return ret; - Step step{start_step_value, start_step_unit}; - std::stringstream ss; + try { + Step step{start_step_value, start_step_unit}; + std::stringstream ss; - ss << step.value(fp_format); + ss << step.value(fp_format); - size_t size = ss.str().size() + 1; + size_t size = ss.str().size() + 1; - if (*len < size) - return GRIB_ARRAY_TOO_SMALL; + if (*len < size) + return GRIB_ARRAY_TOO_SMALL; - *len = size; + *len = size; - memcpy(val, ss.str().c_str(), size); + memcpy(val, ss.str().c_str(), size); + } + catch (std::exception& e) { + grib_context_log(h->context, GRIB_LOG_ERROR, "step_in_units: %s", e.what()); + return GRIB_DECODING_ERROR; + } return GRIB_SUCCESS; } From 6e1c08e290379e16a18ef561e5575f80cc22b483 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 19 Oct 2023 07:51:18 +0000 Subject: [PATCH 081/125] ECC-1620: Change long -> uint64_t --- src/step_unit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/step_unit.h b/src/step_unit.h index 7dc7eeb33..5fe457ad2 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -142,7 +142,7 @@ private: struct Entry { Value unit_value; std::string unit_name; - long duration; + uint64_t duration; }; const std::array tab_ = {{ From 094a055e1634af7956461a2f3f556a5eb1df3edf Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 19 Oct 2023 08:29:24 +0000 Subject: [PATCH 082/125] ECC-1620: Better variable name for selected step units allowed in a GRIB file --- src/step.cc | 6 +++--- src/step_unit.cc | 2 +- src/step_unit.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/step.cc b/src/step.cc index ac7b3bed3..a5fc057c6 100644 --- a/src/step.cc +++ b/src/step.cc @@ -114,11 +114,11 @@ std::pair find_common_units(const Step& startStep, const Step& endSt b.recalculateValue(); } else { - auto it = std::find_if(Unit::publicly_visible_units_.begin(), Unit::publicly_visible_units_.end(), [&](const auto& e) { + auto it = std::find_if(Unit::grib_selected_units.begin(), Unit::grib_selected_units.end(), [&](const auto& e) { return e == a.unit().value() || e == b.unit().value(); }); - assert(it != Unit::publicly_visible_units_.end()); + assert(it != Unit::grib_selected_units.end()); a.set_unit(*it); b.set_unit(*it); @@ -165,7 +165,7 @@ Step& Step::optimize_unit() unit_ = internal_unit_; Seconds seconds = to_seconds(internal_value_, internal_unit_); - for (auto it = Unit::publicly_visible_units_.rbegin(); it != Unit::publicly_visible_units_.rend(); ++it) { + for (auto it = Unit::grib_selected_units.rbegin(); it != Unit::grib_selected_units.rend(); ++it) { long multiplier = Unit::get_converter().unit_to_duration(*it); if (seconds.count() % multiplier == 0) { internal_value_ = seconds.count() / multiplier; diff --git a/src/step_unit.cc b/src/step_unit.cc index 54db81487..e356d4ba4 100644 --- a/src/step_unit.cc +++ b/src/step_unit.cc @@ -12,7 +12,7 @@ Unit::Map Unit::map_{}; -std::vector Unit::publicly_visible_units_ = { +std::vector Unit::grib_selected_units = { Unit::Value::SECOND, Unit::Value::MINUTE, Unit::Value::HOUR, diff --git a/src/step_unit.h b/src/step_unit.h index 5fe457ad2..ee9ae3638 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -93,7 +93,7 @@ public: template T value() const; - static std::vector publicly_visible_units_; + static std::vector grib_selected_units; static std::vector complete_unit_order_; static std::vector list_supported_units() { From 55f501f8b5e1d1bb88543c2607e6970ce1fed3b4 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 19 Oct 2023 12:06:32 +0000 Subject: [PATCH 083/125] ECC-1620: Rename shadowed variable: value --- src/step_unit.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/step_unit.h b/src/step_unit.h index ee9ae3638..0842014de 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -98,10 +98,10 @@ public: static std::vector list_supported_units() { std::vector result; - for (const auto& value : complete_unit_order_) { - if (value == Value::MISSING) + for (const auto& val : complete_unit_order_) { + if (val == Value::MISSING) continue; - result.push_back(Unit(value)); + result.push_back(Unit(val)); } return result; From ece252800a59b04a20748a6021ba0c4e3ce3df02 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 19 Oct 2023 12:10:48 +0000 Subject: [PATCH 084/125] ECC-1620: Remove sanity_check() for steps --- src/step.cc | 9 --------- src/step.h | 1 - 2 files changed, 10 deletions(-) diff --git a/src/step.cc b/src/step.cc index a5fc057c6..13445d69e 100644 --- a/src/step.cc +++ b/src/step.cc @@ -130,20 +130,11 @@ std::pair find_common_units(const Step& startStep, const Step& endSt return {a, b}; } -void Step::sanity_check() 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::init_long(long value, const Unit& unit) { internal_value_ = value; internal_unit_ = unit; unit_ = internal_unit_; - sanity_check(); } void Step::init_double(double value, const Unit& unit) diff --git a/src/step.h b/src/step.h index 2397e77d3..624e751ac 100644 --- a/src/step.h +++ b/src/step.h @@ -74,7 +74,6 @@ public: private: void init_long(long value, const Unit& unit); void init_double(double value, const Unit& unit); - void sanity_check() const; Step& recalculateValue() { if (internal_value_ == 0) { internal_unit_ = unit_; From 6a24296bb1cfa74786b9c791caf141332011aed7 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 19 Oct 2023 13:14:32 +0000 Subject: [PATCH 085/125] ECC-1620: Cleanup and comment --- src/step.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/step.cc b/src/step.cc index 13445d69e..f51718d23 100644 --- a/src/step.cc +++ b/src/step.cc @@ -175,9 +175,10 @@ std::string Step::value(const std::string& format) const { char output[128]; //Do not use variable-length arrays std::string u; - if (unit_ == Unit::Value::HOUR) - u = ""; - else + // Do not print unit if it is HOUR to keep backward compatibility + // with previous versions of ecCodes. This is a temporary solution. + + if (unit_ != Unit::Value::HOUR) u = unit_.value(); int err = snprintf(output, max_size, (format + "%s").c_str(), value(), u.c_str()); From ca4b70307c2ceb2b9e973bcff19e54a54df5ee84 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 19 Oct 2023 15:34:22 +0000 Subject: [PATCH 086/125] ECC-1620: Switch to uint64_t for duration and minor fixes --- src/step.cc | 16 +++++++++------- src/step.h | 2 +- src/step_unit.h | 6 +++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/step.cc b/src/step.cc index f51718d23..6d2fd1452 100644 --- a/src/step.cc +++ b/src/step.cc @@ -139,7 +139,7 @@ void Step::init_long(long value, const Unit& unit) void Step::init_double(double value, const Unit& unit) { - long seconds = Unit::get_converter().unit_to_duration(unit.value()); + auto seconds = Unit::get_converter().unit_to_duration(unit.value()); init_long(static_cast(value * seconds), Unit{Unit::Value::SECOND}); unit_ = unit; } @@ -157,7 +157,7 @@ Step& Step::optimize_unit() Seconds seconds = to_seconds(internal_value_, internal_unit_); for (auto it = Unit::grib_selected_units.rbegin(); it != Unit::grib_selected_units.rend(); ++it) { - long multiplier = Unit::get_converter().unit_to_duration(*it); + auto multiplier = Unit::get_converter().unit_to_duration(*it); if (seconds.count() % multiplier == 0) { internal_value_ = seconds.count() / multiplier; internal_unit_ = *it; @@ -171,18 +171,20 @@ Step& Step::optimize_unit() template <> std::string Step::value(const std::string& format) const { - constexpr int max_size = 128; - char output[128]; //Do not use variable-length arrays + constexpr int MAX_SIZE = 128; + char output[MAX_SIZE]; std::string u; // Do not print unit if it is HOUR to keep backward compatibility - // with previous versions of ecCodes. This is a temporary solution. + // with previous versions of ecCodes (see ECC-1620). This is a temporary solution. + // + // TODO(maee): Remove this code to enable future output, e.g., 15h. if (unit_ != Unit::Value::HOUR) u = unit_.value(); - int err = snprintf(output, max_size, (format + "%s").c_str(), value(), u.c_str()); - if (err < 0 || err >= max_size) { + int err = snprintf(output, MAX_SIZE, (format + "%s").c_str(), value(), u.c_str()); + if (err < 0 || err >= MAX_SIZE) { throw std::runtime_error("Error while formatting Step to string"); } return output; diff --git a/src/step.h b/src/step.h index 624e751ac..f033a409c 100644 --- a/src/step.h +++ b/src/step.h @@ -81,7 +81,7 @@ private: } Seconds seconds = to_seconds(internal_value_, internal_unit_); - long multiplier = Unit::get_converter().unit_to_duration(unit_.value()); + auto multiplier = Unit::get_converter().unit_to_duration(unit_.value()); internal_value_ = seconds.count() / multiplier; internal_unit_ = unit_; diff --git a/src/step_unit.h b/src/step_unit.h index 0842014de..4bfd23290 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -131,7 +131,7 @@ private: Value name_to_unit(const std::string& name) const {return name_to_value_.at(name);} // unit_value <-> duration - long unit_to_duration(const Value& unit_value) const {return value_to_duration_.at(unit_value);} + uint64_t unit_to_duration(const Value& unit_value) const {return value_to_duration_.at(unit_value);} Value duration_to_unit(long duration) const {return duration_to_value_.at(duration);} // wmo_code <-> unit_name @@ -169,8 +169,8 @@ private: std::unordered_map value_to_long_; std::unordered_map long_to_value_; - std::unordered_map value_to_duration_; - std::unordered_map duration_to_value_; + std::unordered_map value_to_duration_; + std::unordered_map duration_to_value_; }; From 141f788ae9b2861f52b1054aba90c04c46b8e240 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Thu, 2 Nov 2023 22:03:09 +0000 Subject: [PATCH 087/125] ECC-1620: Change default step type to string --- src/grib_accessor_class_g2end_step.cc | 16 +++++++++++----- src/grib_accessor_class_step_in_units.cc | 12 ++++++++++-- tools/grib_tools.cc | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index bb398e5ea..b2d4bd1f0 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -23,8 +23,9 @@ IMPLEMENTS = unpack_double IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = init;dump - MEMBERS = const char* start_step_value // startStep - MEMBERS = const char* step_units // stepUnits + IMPLEMENTS = get_native_type + MEMBERS = const char* start_step_value + MEMBERS = const char* step_units MEMBERS = const char* year MEMBERS = const char* month @@ -59,10 +60,11 @@ or edit "accessor.class" and rerun ./make_class.pl */ +static int get_native_type(grib_accessor*); 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_long(grib_accessor*, long* val, 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 void dump(grib_accessor*, grib_dumper*); static void init(grib_accessor*, const long, grib_arguments*); @@ -95,7 +97,6 @@ typedef struct grib_accessor_g2end_step extern grib_accessor_class* grib_accessor_class_long; - static grib_accessor_class _grib_accessor_class_g2end_step = { &grib_accessor_class_long, /* super */ "g2end_step", /* name */ @@ -111,7 +112,7 @@ static grib_accessor_class _grib_accessor_class_g2end_step = { 0, /* get number of values */ 0, /* get number of bytes */ 0, /* get offset to bytes */ - 0, /* get native type */ + &get_native_type, /* get native type */ 0, /* get sub_section */ 0, /* pack_missing */ 0, /* is_missing */ @@ -721,3 +722,8 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) } return GRIB_SUCCESS; } + +static int get_native_type(grib_accessor* a) +{ + return GRIB_TYPE_STRING; +} diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index d88c8c62c..2fbc43123 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -22,6 +22,7 @@ IMPLEMENTS = unpack_double IMPLEMENTS = unpack_string;pack_string IMPLEMENTS = init;dump + IMPLEMENTS = get_native_type MEMBERS = const char* forecast_time_value MEMBERS = const char* forecast_time_unit MEMBERS = const char* step_units @@ -42,10 +43,11 @@ or edit "accessor.class" and rerun ./make_class.pl */ +static int get_native_type(grib_accessor*); 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_long(grib_accessor*, long* val, 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 void dump(grib_accessor*, grib_dumper*); static void init(grib_accessor*, const long, grib_arguments*); @@ -80,7 +82,7 @@ static grib_accessor_class _grib_accessor_class_step_in_units = { 0, /* get number of values */ 0, /* get number of bytes */ 0, /* get offset to bytes */ - 0, /* get native type */ + &get_native_type, /* get native type */ 0, /* get sub_section */ 0, /* pack_missing */ 0, /* is_missing */ @@ -334,3 +336,9 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return GRIB_SUCCESS; } + + +static int get_native_type(grib_accessor* a) +{ + return GRIB_TYPE_STRING; +} diff --git a/tools/grib_tools.cc b/tools/grib_tools.cc index f3c2ce82f..8e831de29 100644 --- a/tools/grib_tools.cc +++ b/tools/grib_tools.cc @@ -756,7 +756,7 @@ static void grib_tools_set_print_keys(grib_runtime_options* options, grib_handle options->default_print_width = (int)strlen(name); options->print_keys[options->print_keys_count].type = GRIB_TYPE_STRING; if (strcmp(ns, "mars") == 0 && (strcmp(name, "step") == 0)) { - options->print_keys[options->print_keys_count].type = GRIB_TYPE_UNDEFINED; + options->print_keys[options->print_keys_count].type = GRIB_TYPE_LONG; } // For the statistics namespace, do not force the type to be string. // Setting it to undefined will use the keys' native type i.e. GRIB_TYPE_DOUBLE From ea69d2927f4306c53338cc04cfe55a6e29b2704a Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 3 Nov 2023 12:07:41 +0000 Subject: [PATCH 088/125] ECC-1620: Fix negative steps --- src/step.cc | 11 +++++------ src/step.h | 2 +- tests/grib_ecc-1620.sh | 3 +++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/step.cc b/src/step.cc index 6d2fd1452..23318d27e 100644 --- a/src/step.cc +++ b/src/step.cc @@ -75,16 +75,14 @@ bool Step::operator<(const Step& step) const Step Step::operator+(const Step& step) const { - Step tmp = step; - auto [a, b] = find_common_units(this->copy().optimize_unit(), tmp.copy().optimize_unit()); + auto [a, b] = find_common_units(this->copy().optimize_unit(), step.copy().optimize_unit()); assert(a.internal_unit_ == b.internal_unit_); return Step(a.internal_value_ + b.internal_value_, a.internal_unit_); } Step Step::operator-(const Step& step) const { - Step tmp = step; - auto [a, b] = find_common_units(this->copy().optimize_unit(), tmp.copy().optimize_unit()); + auto [a, b] = find_common_units(this->copy().optimize_unit(), step.copy().optimize_unit()); assert(a.internal_unit_ == b.internal_unit_); return Step(a.internal_value_ - b.internal_value_, a.internal_unit_); } @@ -155,10 +153,11 @@ Step& Step::optimize_unit() unit_ = internal_unit_; Seconds seconds = to_seconds(internal_value_, internal_unit_); + long abs_seconds = seconds.count() < 0 ? -seconds.count() : seconds.count(); for (auto it = Unit::grib_selected_units.rbegin(); it != Unit::grib_selected_units.rend(); ++it) { - auto multiplier = Unit::get_converter().unit_to_duration(*it); - if (seconds.count() % multiplier == 0) { + long multiplier = Unit::get_converter().unit_to_duration(*it); + if (abs_seconds % multiplier == 0) { internal_value_ = seconds.count() / multiplier; internal_unit_ = *it; unit_ = *it; diff --git a/src/step.h b/src/step.h index f033a409c..624e751ac 100644 --- a/src/step.h +++ b/src/step.h @@ -81,7 +81,7 @@ private: } Seconds seconds = to_seconds(internal_value_, internal_unit_); - auto multiplier = Unit::get_converter().unit_to_duration(unit_.value()); + long multiplier = Unit::get_converter().unit_to_duration(unit_.value()); internal_value_ = seconds.count() / multiplier; internal_unit_ = unit_; diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index fb539b7d8..d7452ce68 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -56,6 +56,9 @@ grib_check_key_equals $temp "-s stepUnits:s=h -p startStep:s,endStep:s" "-6 0" grib_check_key_equals $temp "-s stepUnits:s=m -p startStep:s,endStep:s" "-360m 0m" grib_check_key_equals $temp "-s stepUnits:s=s -p startStep:s,endStep:s" "-21600s 0s" +${tools_dir}/grib_set -s forecastTime=-48,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=0,indicatorOfUnitForTimeRange=h $fn $temp +grib_check_key_equals $temp "-p stepRange" "-48" + #### CHECK: check optimal units are set correctly in GRIB files fn="${data_dir}/reduced_gaussian_sub_area.grib2" From 372ba12ddc37be7778a17882aaee8c99c829c0a2 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 3 Nov 2023 12:16:04 +0000 Subject: [PATCH 089/125] ECC-1620: Switch default step type to string --- tests/grib_ecc-1620.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index d7452ce68..c999ac42e 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -177,8 +177,8 @@ keys_i="step:i,stepUnits:s" keys_d="step:d,stepUnits:s" ${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp -grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "3540 s" -grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "59 m" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "3540s s" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "59m m" #grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0" # TODO(EB): check behaviour (should be 0.983333) grib_check_key_equals $temp "-p $keys_s -s stepUnits=s" "3540s" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "59m" @@ -209,13 +209,13 @@ keys_d="step:d,stepUnits:s" ${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 m" +grib_check_key_equals $temp "-p $keys__" "0m m" grib_check_key_equals $temp "-p $keys_s" "0m m" grib_check_key_equals $temp "-p $keys_i" "0 m" grib_check_key_equals $temp "-p $keys_d" "0 m" -grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "0 s" -grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "0 m" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "0s s" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "0m m" grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0 h" grib_check_key_equals $temp "-p $keys_s -s stepUnits=s" "0s s" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "0m m" @@ -229,8 +229,8 @@ grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0 h" ${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "59 m" -grib_check_key_equals $temp "-p $keys__" "59 m" +grib_check_key_equals $temp "-p $low_level_keys" "59 m" +grib_check_key_equals $temp "-p $keys__" "59m m" #grib_check_key_equals $temp "-p $keys_s" "59" grib_check_key_equals $temp "-p $keys_s" "59m m" grib_check_key_equals $temp "-p $keys_i" "59 m" @@ -245,7 +245,7 @@ grib_check_key_equals $temp "-p $keys_d" "1 h" ${tools_dir}/grib_set -s forecastTime=61,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "61 m" -grib_check_key_equals $temp "-p $keys__" "61 m" +grib_check_key_equals $temp "-p $keys__" "61m m" #grib_check_key_equals $temp "-p $keys_s" "61" grib_check_key_equals $temp "-p $keys_s" "61m m" grib_check_key_equals $temp "-p $keys_i" "61 m" @@ -303,7 +303,7 @@ grib_check_key_equals $temp "-p $keys_d" "49 25 49" ${tools_dir}/grib_set -s forecastTime=45,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=15,indicatorOfUnitForTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "45 m 15 m" -grib_check_key_equals $temp "-p $keys__" "45m-60m 45 60" +grib_check_key_equals $temp "-p $keys__" "45m-60m 45m 60m" #grib_check_key_equals $temp "-p $keys_s" "45-60 45 60" grib_check_key_equals $temp "-p $keys_s" "45m-60m 45m 60m" grib_check_key_equals $temp "-p $keys_i" "60 45 60" From 60ebb29450a85c15f59c23cce52b1867f2ca5252 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 3 Nov 2023 12:26:00 +0000 Subject: [PATCH 090/125] ECC-1620: Default step type: string --- tests/grib_ecc-1620.sh | 28 ++++++++++++++-------------- tests/grib_step.sh | 16 ++++++++-------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index c999ac42e..2416e15a2 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -208,7 +208,7 @@ keys_i="step:i,stepUnits:s" keys_d="step:d,stepUnits:s" ${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 $low_level_keys" "0 m" grib_check_key_equals $temp "-p $keys__" "0m m" grib_check_key_equals $temp "-p $keys_s" "0m m" grib_check_key_equals $temp "-p $keys_i" "0 m" @@ -237,14 +237,14 @@ grib_check_key_equals $temp "-p $keys_i" "59 m" grib_check_key_equals $temp "-p $keys_d" "59 m" ${tools_dir}/grib_set -s forecastTime=60,indicatorOfUnitOfTimeRange=m $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "60 m" +grib_check_key_equals $temp "-p $low_level_keys" "60 m" grib_check_key_equals $temp "-p $keys__" "1 h" grib_check_key_equals $temp "-p $keys_s" "1 h" grib_check_key_equals $temp "-p $keys_i" "1 h" grib_check_key_equals $temp "-p $keys_d" "1 h" ${tools_dir}/grib_set -s forecastTime=61,indicatorOfUnitOfTimeRange=m $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "61 m" +grib_check_key_equals $temp "-p $low_level_keys" "61 m" grib_check_key_equals $temp "-p $keys__" "61m m" #grib_check_key_equals $temp "-p $keys_s" "61" grib_check_key_equals $temp "-p $keys_s" "61m m" @@ -252,14 +252,14 @@ grib_check_key_equals $temp "-p $keys_i" "61 m" grib_check_key_equals $temp "-p $keys_d" "61 m" ${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "24 h" +grib_check_key_equals $temp "-p $low_level_keys" "24 h" grib_check_key_equals $temp "-p $keys__" "24 h" grib_check_key_equals $temp "-p $keys_s" "24 h" grib_check_key_equals $temp "-p $keys_i" "24 h" grib_check_key_equals $temp "-p $keys_d" "24 h" ${tools_dir}/grib_set -s forecastTime=1440,indicatorOfUnitOfTimeRange=m $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "1440 m" +grib_check_key_equals $temp "-p $low_level_keys" "1440 m" grib_check_key_equals $temp "-p $keys__" "24 h" grib_check_key_equals $temp "-p $keys_s" "24 h" grib_check_key_equals $temp "-p $keys_i" "24 h" @@ -280,29 +280,29 @@ keys_i="stepRange:i,startStep:i,endStep:i" keys_d="stepRange:d,startStep:d,endStep:d" ${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=2,indicatorOfUnitForTimeRange=h $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "0 m 2 h" +grib_check_key_equals $temp "-p $low_level_keys" "0 m 2 h" grib_check_key_equals $temp "-p $keys__" "0-2 0 2" grib_check_key_equals $temp "-p $keys_s" "0-2 0 2" grib_check_key_equals $temp "-p $keys_i" "2 0 2" grib_check_key_equals $temp "-p $keys_d" "2 0 2" ${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" +grib_check_key_equals $temp "-p $low_level_keys" "24 h 1 D" grib_check_key_equals $temp "-p $keys__" "24-48 24 48" grib_check_key_equals $temp "-p $keys_s" "24-48 24 48" grib_check_key_equals $temp "-p $keys_i" "48 24 48" grib_check_key_equals $temp "-p $keys_d" "48 24 48" ${tools_dir}/grib_set -s forecastTime=25,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=1,indicatorOfUnitForTimeRange=D $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "25 h 1 D" -grib_check_key_equals $temp "-p $keys__" "25-49 25 49" +grib_check_key_equals $temp "-p $low_level_keys" "25 h 1 D" +grib_check_key_equals $temp "-p $keys__" "25-49 25 49" grib_check_key_equals $temp "-p $keys__" "25-49 25 49" grib_check_key_equals $temp "-p $keys_s" "25-49 25 49" grib_check_key_equals $temp "-p $keys_i" "49 25 49" grib_check_key_equals $temp "-p $keys_d" "49 25 49" ${tools_dir}/grib_set -s forecastTime=45,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=15,indicatorOfUnitForTimeRange=m $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "45 m 15 m" +grib_check_key_equals $temp "-p $low_level_keys" "45 m 15 m" grib_check_key_equals $temp "-p $keys__" "45m-60m 45m 60m" #grib_check_key_equals $temp "-p $keys_s" "45-60 45 60" grib_check_key_equals $temp "-p $keys_s" "45m-60m 45m 60m" @@ -310,28 +310,28 @@ grib_check_key_equals $temp "-p $keys_i" "60 45 60" grib_check_key_equals $temp "-p $keys_d" "60 45 60" ${tools_dir}/grib_set -s forecastTime=60,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=2,indicatorOfUnitForTimeRange=h $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "60 m 2 h" +grib_check_key_equals $temp "-p $low_level_keys" "60 m 2 h" grib_check_key_equals $temp "-p $keys__" "1-3 1 3" grib_check_key_equals $temp "-p $keys_s" "1-3 1 3" grib_check_key_equals $temp "-p $keys_i" "3 1 3" grib_check_key_equals $temp "-p $keys_d" "3 1 3" ${tools_dir}/grib_set -s forecastTime=18,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=6,indicatorOfUnitForTimeRange=h $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "18 h 6 h" +grib_check_key_equals $temp "-p $low_level_keys" "18 h 6 h" grib_check_key_equals $temp "-p $keys__" "18-24 18 24" grib_check_key_equals $temp "-p $keys_s" "18-24 18 24" grib_check_key_equals $temp "-p $keys_i" "24 18 24" grib_check_key_equals $temp "-p $keys_d" "24 18 24" ${tools_dir}/grib_set -s forecastTime=1080,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=360,indicatorOfUnitForTimeRange=m $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "1080 m 360 m" +grib_check_key_equals $temp "-p $low_level_keys" "1080 m 360 m" grib_check_key_equals $temp "-p $keys__" "18-24 18 24" grib_check_key_equals $temp "-p $keys_s" "18-24 18 24" grib_check_key_equals $temp "-p $keys_i" "24 18 24" grib_check_key_equals $temp "-p $keys_d" "24 18 24" ${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" +grib_check_key_equals $temp "-p $low_level_keys" "1080 m 6 h" grib_check_key_equals $temp "-p $keys__" "18-24 18 24" grib_check_key_equals $temp "-p $keys_s" "18-24 18 24" grib_check_key_equals $temp "-p $keys_i" "24 18 24" diff --git a/tests/grib_step.sh b/tests/grib_step.sh index 741da1867..d452de0a1 100755 --- a/tests/grib_step.sh +++ b/tests/grib_step.sh @@ -182,28 +182,28 @@ result=$( ${tools_dir}/grib_get -p dataTime -s hour=2,minute=255 $input ) # Various step units # -------------------- input=${data_dir}/tigge_cf_ecmwf.grib2 -result=$(${tools_dir}/grib_get -w count=1 -p step -s stepUnits=h $input) +result=$(${tools_dir}/grib_get -w count=1 -p step:i -s stepUnits=h $input) [ $result = 96 ] -result=$(${tools_dir}/grib_get -w count=1 -p step -s stepUnits=30m $input) +result=$(${tools_dir}/grib_get -w count=1 -p step:i -s stepUnits=30m $input) [ $result = 192 ] -result=$(${tools_dir}/grib_get -w count=1 -p step -s stepUnits=15m $input) +result=$(${tools_dir}/grib_get -w count=1 -p step:i -s stepUnits=15m $input) [ $result = 384 ] -result=$(${tools_dir}/grib_get -w count=1 -p step -s stepUnits=s $input) +result=$(${tools_dir}/grib_get -w count=1 -p step:i -s stepUnits=s $input) [ $result = 345600 ] -result=$(${tools_dir}/grib_get -w count=1 -p step -s stepUnits=12h $input) +result=$(${tools_dir}/grib_get -w count=1 -p step:i -s stepUnits=12h $input) [ $result = 8 ] -result=$(${tools_dir}/grib_get -w count=1 -p step -s stepUnits=6h $input) +result=$(${tools_dir}/grib_get -w count=1 -p step:i -s stepUnits=6h $input) [ $result = 16 ] -result=$(${tools_dir}/grib_get -w count=1 -p step -s stepUnits=D $input) +result=$(${tools_dir}/grib_get -w count=1 -p step:i -s stepUnits=D $input) [ $result = 4 ] -result=$(${tools_dir}/grib_get -w count=1 -p step -s stepUnits=m $input) +result=$(${tools_dir}/grib_get -w count=1 -p step:i -s stepUnits=m $input) [ $result = 5760 ] # GRIB1 stepRange and timeRangeIndicator=10 From d6b9fae892791d94035b882c5c1d3e7d609c35d8 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 6 Nov 2023 10:18:01 +0000 Subject: [PATCH 091/125] ECC-1620: Special handling of 15m and 30m units --- src/step.cc | 7 ++++++- tests/grib_ecc-1620.sh | 41 +++++++++++++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/step.cc b/src/step.cc index 23318d27e..a5baacd88 100644 --- a/src/step.cc +++ b/src/step.cc @@ -173,6 +173,7 @@ std::string Step::value(const std::string& format) const { constexpr int MAX_SIZE = 128; char output[MAX_SIZE]; std::string u; + int err; // Do not print unit if it is HOUR to keep backward compatibility // with previous versions of ecCodes (see ECC-1620). This is a temporary solution. @@ -182,7 +183,11 @@ std::string Step::value(const std::string& format) const { if (unit_ != Unit::Value::HOUR) u = unit_.value(); - int err = snprintf(output, MAX_SIZE, (format + "%s").c_str(), value(), u.c_str()); + if (unit_ == Unit::Value::MINUTES15 || unit_ == Unit::Value::MINUTES30) + err = snprintf(output, MAX_SIZE, (format + "(%s)").c_str(), value(), u.c_str()); + else + err = snprintf(output, MAX_SIZE, (format + "%s").c_str(), value(), u.c_str()); + if (err < 0 || err >= MAX_SIZE) { throw std::runtime_error("Error while formatting Step to string"); } diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 2416e15a2..360c5bfcf 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -46,6 +46,31 @@ temp2=temp_2.$label samples_dir=$ECCODES_SAMPLES_PATH +#### CHECK units +fn="${data_dir}/reduced_gaussian_sub_area.grib2" +low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" +${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=96,indicatorOfUnitForTimeRange=h $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" + +grib_check_key_equals $temp " -w count=1 -s stepUnits=s -p step:i,stepUnits:s" "345600 s" +grib_check_key_equals $temp " -w count=1 -s stepUnits=m -p step:i,stepUnits:s" "5760 m" +grib_check_key_equals $temp " -w count=1 -s stepUnits=15m -p step:i,stepUnits:s" "384 15m" +grib_check_key_equals $temp " -w count=1 -s stepUnits=30m -p step:i,stepUnits:s" "192 30m" +grib_check_key_equals $temp " -w count=1 -s stepUnits=h -p step:i,stepUnits:s" "96 h" +grib_check_key_equals $temp " -w count=1 -s stepUnits=6h -p step:i,stepUnits:s" "16 6h" +grib_check_key_equals $temp " -w count=1 -s stepUnits=12h -p step:i,stepUnits:s" "8 12h" +grib_check_key_equals $temp " -w count=1 -s stepUnits=D -p step:i,stepUnits:s" "4 D" + +grib_check_key_equals $temp " -w count=1 -s stepUnits=s -p step,stepUnits:s" "345600s s" +grib_check_key_equals $temp " -w count=1 -s stepUnits=m -p step,stepUnits:s" "5760m m" +grib_check_key_equals $temp " -w count=1 -s stepUnits=15m -p step,stepUnits:s" "384(15m) 15m" +grib_check_key_equals $temp " -w count=1 -s stepUnits=30m -p step,stepUnits:s" "192(30m) 30m" +grib_check_key_equals $temp " -w count=1 -s stepUnits=h -p step,stepUnits:s" "96 h" +grib_check_key_equals $temp " -w count=1 -s stepUnits=6h -p step,stepUnits:s" "166h 6h" # FIXME(maee) (16(6h) 6h) is correct +grib_check_key_equals $temp " -w count=1 -s stepUnits=12h -p step,stepUnits:s" "812h 12h" # FIXME(maee) (8(12h) 12h) is correct +grib_check_key_equals $temp " -w count=1 -s stepUnits=D -p step,stepUnits:s" "4D D" + + #### CHECK negative forecastTime fn="${data_dir}/reduced_gaussian_sub_area.grib2" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" @@ -66,7 +91,7 @@ low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indi ${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" -### TODO(EB): @Shahram: how to make parameters position independent +### TODO(maee): @Shahram: how to make parameters position independent ${tools_dir}/grib_set -s stepUnits:s=s,startStep:i=60,endStep:i=180 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" #${tools_dir}/grib_set -s startStep:i=60,endStep:i=180,stepUnits:s=s $temp $temp2 @@ -113,11 +138,11 @@ ${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h,lengthOfTi grib_check_key_equals $temp "-p $low_level_keys" "24 h 1 D" # Use range unit: hour -${tools_dir}/grib_set -s endStep:d=30 $temp $temp2 # TODO(EB) remove in the future behavior -#${tools_dir}/grib_set -s endStep:i=30 $temp $temp2 # TODO(EB) keep for backwards compatibility +${tools_dir}/grib_set -s endStep:d=30 $temp $temp2 # TODO(maee) remove in the future behavior +#${tools_dir}/grib_set -s endStep:i=30 $temp $temp2 # TODO(maee) keep for backwards compatibility #${tools_dir}/grib_set -s endStep:s=30 $temp $temp2 #${tools_dir}/grib_set -s endStep:s=30h $temp $temp2 -#${tools_dir}/grib_set -s endStep=30h $temp $temp2 # TODO(EB) add to tests +#${tools_dir}/grib_set -s endStep=30h $temp $temp2 # TODO(maee) add to tests grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 6 h" # Use stepUnits @@ -179,16 +204,16 @@ keys_d="step:d,stepUnits:s" ${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "3540s s" grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "59m m" -#grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0" # TODO(EB): check behaviour (should be 0.983333) +#grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0" # TODO(maee): check behaviour (should be 0.983333) grib_check_key_equals $temp "-p $keys_s -s stepUnits=s" "3540s" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "59m" -#grib_check_key_equals $temp "-p $keys_s -F"%.2f" -s stepUnits=h" "0.983333" # TODO(EB): check behaviour // See tools for default output format +#grib_check_key_equals $temp "-p $keys_s -F"%.2f" -s stepUnits=h" "0.983333" # TODO(maee): check behaviour // See tools for default output format grib_check_key_equals $temp "-p $keys_i -s stepUnits=s" "3540 s" grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "59 m" -#grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0" # TODO(EB): check behaviour +#grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0" # TODO(maee): check behaviour grib_check_key_equals $temp "-p $keys_d -s stepUnits=s" "3540 s" grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "59 m" -#grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0.983333" # TODO(EB): check behaviour +#grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0.983333" # TODO(maee): check behaviour ${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m $fn $temp From 485e2caedc7d2d3f4307de4455df2a797c3e8f5c Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 6 Nov 2023 10:35:52 +0000 Subject: [PATCH 092/125] ECC-1620: Test setting 15m, 30m units --- tests/grib_ecc-1620.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 360c5bfcf..a5e1bb009 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -70,6 +70,23 @@ grib_check_key_equals $temp " -w count=1 -s stepUnits=6h -p step,stepUnits:s" "1 grib_check_key_equals $temp " -w count=1 -s stepUnits=12h -p step,stepUnits:s" "812h 12h" # FIXME(maee) (8(12h) 12h) is correct grib_check_key_equals $temp " -w count=1 -s stepUnits=D -p step,stepUnits:s" "4D D" +${tools_dir}/grib_set -s stepUnits=s,startStep=0,endStep=345600 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +${tools_dir}/grib_set -s stepUnits=m,startStep=0,endStep=5760 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +${tools_dir}/grib_set -s stepUnits=15m,startStep=0,endStep=384 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +${tools_dir}/grib_set -s stepUnits=30m,startStep=0,endStep=192 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +${tools_dir}/grib_set -s stepUnits=h,startStep=0,endStep=96 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +${tools_dir}/grib_set -s stepUnits=6h,startStep=0,endStep=16 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +${tools_dir}/grib_set -s stepUnits=12h,startStep=0,endStep=8 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +${tools_dir}/grib_set -s stepUnits=D,startStep=0,endStep=4 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" + #### CHECK negative forecastTime fn="${data_dir}/reduced_gaussian_sub_area.grib2" From 3bcb5a8cc92eddf15450c9ad39cfe2dd36ca378a Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 29 Nov 2023 09:37:38 +0000 Subject: [PATCH 093/125] ECC-1620: New format for special units, e.g., 8x15m --- src/step.cc | 13 ++++++++++--- tests/grib_ecc-1620.sh | 8 ++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/step.cc b/src/step.cc index a5baacd88..c2ff472b9 100644 --- a/src/step.cc +++ b/src/step.cc @@ -183,9 +183,16 @@ std::string Step::value(const std::string& format) const { if (unit_ != Unit::Value::HOUR) u = unit_.value(); - if (unit_ == Unit::Value::MINUTES15 || unit_ == Unit::Value::MINUTES30) - err = snprintf(output, MAX_SIZE, (format + "(%s)").c_str(), value(), u.c_str()); - else + if (unit_ == Unit::Value::MINUTES15 || + unit_ == Unit::Value::MINUTES30 || + unit_ == Unit::Value::HOURS3 || + unit_ == Unit::Value::HOURS6 || + unit_ == Unit::Value::HOURS12 || + unit_ == Unit::Value::YEARS10 || + unit_ == Unit::Value::YEARS30 + ) + err = snprintf(output, MAX_SIZE, (format + "x%s").c_str(), value(), u.c_str()); + else err = snprintf(output, MAX_SIZE, (format + "%s").c_str(), value(), u.c_str()); if (err < 0 || err >= MAX_SIZE) { diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index a5e1bb009..a08cde285 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -63,11 +63,11 @@ grib_check_key_equals $temp " -w count=1 -s stepUnits=D -p step:i,stepUnits:s" " grib_check_key_equals $temp " -w count=1 -s stepUnits=s -p step,stepUnits:s" "345600s s" grib_check_key_equals $temp " -w count=1 -s stepUnits=m -p step,stepUnits:s" "5760m m" -grib_check_key_equals $temp " -w count=1 -s stepUnits=15m -p step,stepUnits:s" "384(15m) 15m" -grib_check_key_equals $temp " -w count=1 -s stepUnits=30m -p step,stepUnits:s" "192(30m) 30m" +grib_check_key_equals $temp " -w count=1 -s stepUnits=15m -p step,stepUnits:s" "384x15m 15m" +grib_check_key_equals $temp " -w count=1 -s stepUnits=30m -p step,stepUnits:s" "192x30m 30m" grib_check_key_equals $temp " -w count=1 -s stepUnits=h -p step,stepUnits:s" "96 h" -grib_check_key_equals $temp " -w count=1 -s stepUnits=6h -p step,stepUnits:s" "166h 6h" # FIXME(maee) (16(6h) 6h) is correct -grib_check_key_equals $temp " -w count=1 -s stepUnits=12h -p step,stepUnits:s" "812h 12h" # FIXME(maee) (8(12h) 12h) is correct +grib_check_key_equals $temp " -w count=1 -s stepUnits=6h -p step,stepUnits:s" "16x6h 6h" +grib_check_key_equals $temp " -w count=1 -s stepUnits=12h -p step,stepUnits:s" "8x12h 12h" grib_check_key_equals $temp " -w count=1 -s stepUnits=D -p step,stepUnits:s" "4D D" ${tools_dir}/grib_set -s stepUnits=s,startStep=0,endStep=345600 $fn $temp From eec53eb56b5ddcae734acbb98c504434eda03ecc Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 29 Nov 2023 14:22:36 +0000 Subject: [PATCH 094/125] ECC-1620: Force stepUnits --- src/grib_accessor_class_g2end_step.cc | 20 +++- src/grib_accessor_class_g2step_range.cc | 21 +++- src/grib_accessor_class_optimal_step_units.cc | 2 +- src/grib_accessor_class_step_in_units.cc | 20 ++-- src/step.cc | 31 ++++-- src/step.h | 4 +- tests/grib_ecc-1620.sh | 96 +++++++++++++------ 7 files changed, 142 insertions(+), 52 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index b2d4bd1f0..0bd8d70ab 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -569,6 +569,10 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if ((err = grib_get_long_internal(h, "startStepUnit", &start_step_unit))) return err; + long force_step_units; + if ((err= grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) + return err; + if (Unit{start_step_unit} == Unit{Unit::Value::MISSING}) { grib_context_log(h->context, GRIB_LOG_ERROR, "missing start step unit"); @@ -615,7 +619,15 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en const char* forecast_time_value_key = "forecastTime"; const char* forecast_time_unit_key = "indicatorOfUnitOfTimeRange"; - auto [forecast_time_opt, time_range_opt] = find_common_units(start_step.optimize_unit(), time_range.optimize_unit()); + Step forecast_time_opt; + Step time_range_opt; + if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { + std::tie(forecast_time_opt, time_range_opt) = find_common_units(start_step.optimize_unit(), time_range.optimize_unit()); + } + else { + forecast_time_opt = Step{start_step.value(Unit{force_step_units}), Unit{force_step_units}}; + time_range_opt = Step{time_range.value(Unit{force_step_units}), Unit{force_step_units}}; + } if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range_opt.value())) != GRIB_SUCCESS) return err; @@ -706,8 +718,12 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); int ret = 0; + long force_step_units; + if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) + return ret; + try { - Step end_step = step_from_string(val); + Step end_step = step_from_string(val, Unit{force_step_units}); end_step.optimize_unit(); if ((ret = grib_set_long_internal(h, "endStepUnit", end_step.unit().value())) != GRIB_SUCCESS) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index d93358a94..1260f44c2 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -199,17 +199,30 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) grib_handle* h = grib_handle_of_accessor(a); int ret = 0; + long force_step_units; + if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) + return ret; + try { - std::vector steps = parse_range(val); + std::vector steps = parse_range(val, Unit{force_step_units}); if (steps.size() == 0) { grib_context_log(a->context, GRIB_LOG_ERROR, "Could not parse step range: %s", val); return GRIB_INVALID_ARGUMENT; } - Step step_0 = steps[0]; + Step step_0; Step step_1; - if (steps.size() > 1) { - std::tie(step_0, step_1) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); + if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { + if (steps.size() > 1) + std::tie(step_0, step_1) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); + else + step_0 = steps[0].optimize_unit(); + } + else { + step_0 = Step{steps[0].value(Unit{force_step_units}), Unit{force_step_units}}; + if (steps.size() > 1) { + step_1 = Step{steps[1].value(Unit{force_step_units}), Unit{force_step_units}}; + } } if ((ret = grib_set_long_internal(h, "startStepUnit", step_0.unit().value()))) diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 362415299..5d297b96c 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -157,7 +157,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) supported_units_str += Unit{u}.value() + ","; supported_units_str.pop_back(); - std::string msg = std::string{"Invalid unit: "} + std::to_string(*val) + " (" + e.what() + ")" + ". Available X tunits are: " + supported_units_str; + std::string msg = std::string{"Invalid unit: "} + std::to_string(*val) + " (" + e.what() + ")" + ". Available units are: " + supported_units_str; grib_context_log(a->context, GRIB_LOG_ERROR, msg.c_str()); return GRIB_INVALID_ARGUMENT; } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index 2fbc43123..b7faa5859 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -198,7 +198,7 @@ static int unpack_double(grib_accessor* a, double * val, size_t* len) return GRIB_SUCCESS; } -static int pack_long_new_(grib_accessor* a, const long start_step_value, const long start_step_unit) +static int pack_long_new_(grib_accessor* a, const long start_step_value, const long start_step_unit, const long force_step_units) { grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a; grib_handle* h = grib_handle_of_accessor(a); @@ -236,7 +236,10 @@ static int pack_long_new_(grib_accessor* a, const long start_step_value, const l return GRIB_SUCCESS; } - forecast_time.optimize_unit(); + if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { + forecast_time.optimize_unit(); + } + if ((err = grib_set_long_internal(h, "startStepUnit", forecast_time.unit().value())) != GRIB_SUCCESS) return err; if ((err = set_step(h, self->forecast_time_value, self->forecast_time_unit, forecast_time)) != GRIB_SUCCESS) @@ -272,18 +275,23 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) return GRIB_DECODING_ERROR; } - ret = pack_long_new_(a, *val, start_step_unit); + ret = pack_long_new_(a, *val, start_step_unit, force_step_units); return ret; } static int pack_string(grib_accessor* a, const char* val, size_t* len) { + grib_handle* h = grib_handle_of_accessor(a); + //long force_step_units = Unit(Unit::Value::MISSING).value(); int ret = GRIB_SUCCESS; - try { - Step step = step_from_string(val); + long force_step_units; + if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) + return ret; - if ((ret = pack_long_new_(a, step.value(), step.unit().value())) != GRIB_SUCCESS) + try { + Step step = step_from_string(val, Unit{force_step_units}); + if ((ret = pack_long_new_(a, step.value(), step.unit().value(), force_step_units)) != GRIB_SUCCESS) return ret; } catch (std::exception& e) { diff --git a/src/step.cc b/src/step.cc index c2ff472b9..d26a47128 100644 --- a/src/step.cc +++ b/src/step.cc @@ -20,34 +20,44 @@ #include "step_unit.h" #include "step.h" -Step step_from_string(std::string step) +Step step_from_string(const std::string& step, const Unit& force_unit) { 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"; + std::string unit_str = match[2]; + Unit unit; + if (unit_str.size() != 0) { + if (force_unit == Unit{Unit::Value::MISSING}) + unit = Unit{unit_str}; + else + throw std::runtime_error("Cannot force unit when unit is specified in step string"); } - Step ret{std::stod(value), Unit{unit}}; + else { + if (force_unit == Unit{Unit::Value::MISSING}) + unit = Unit{Unit::Value::HOUR}; + else + unit = force_unit; + } + Step ret{std::stod(value), unit}; return ret; } } throw std::runtime_error("Could not parse step: " + step); } -std::vector parse_range(const std::string& range_str) +std::vector parse_range(const std::string& range_str, const Unit& force_unit) { 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))); + steps.push_back(step_from_string(range_str.substr(prev, pos - prev), force_unit)); prev = pos + 1; } - steps.push_back(step_from_string(range_str.substr(prev))); + steps.push_back(step_from_string(range_str.substr(prev), force_unit)); return steps; } @@ -132,13 +142,14 @@ void Step::init_long(long value, const Unit& unit) { internal_value_ = value; internal_unit_ = unit; - unit_ = internal_unit_; + unit_ = unit; } void Step::init_double(double value, const Unit& unit) { auto seconds = Unit::get_converter().unit_to_duration(unit.value()); - init_long(static_cast(value * seconds), Unit{Unit::Value::SECOND}); + internal_value_ = value * seconds; + internal_unit_ = Unit{Unit::Value::SECOND}; unit_ = unit; } diff --git a/src/step.h b/src/step.h index 624e751ac..79afdaeb1 100644 --- a/src/step.h +++ b/src/step.h @@ -94,8 +94,8 @@ private: }; -Step step_from_string(std::string step); -std::vector parse_range(const std::string& range_str); +Step step_from_string(const std::string& step, const Unit& force_unit); +std::vector parse_range(const std::string& range_str, const Unit& force_unit); std::pair find_common_units(const Step& startStep, const Step& endStep); diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index a08cde285..b7a0449c7 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -45,9 +45,49 @@ temp=temp.$label temp2=temp_2.$label samples_dir=$ECCODES_SAMPLES_PATH +instantaneous_field=$data_dir/reduced_gaussian_surface.grib2 +accumulated_field=$data_dir/reduced_gaussian_sub_area.grib2 + +# if stepUnits is set, then set the low level keys to stepUnits +# if stepUnits is not set, then optimise low level keys +# instant fields: +low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" +fn="$instantaneous_field" +low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s" +keys__="step,stepUnits:s" +keys_s="step:s" +keys_i="step:i,stepUnits:s" +keys_d="step:d,stepUnits:s" + +${tools_dir}/grib_set -s stepUnits=m,step=60 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "60 m" +grib_check_key_equals $temp "-p $keys_s" "1" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "60m" +${tools_dir}/grib_set -s step=60m $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "1 h" +grib_check_key_equals $temp "-p $keys_s" "1" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "60m" + + +# accumulated fields: +fn="$accumulated_field" +low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" +keys__="step,startStep,endStep,stepRange,stepUnits:s" +keys_s="step:s,startStep:s,endStep:s,stepRange:s,stepUnits:s" +keys_i="step:i,startStep:i,endStep:i,stepRange:i,stepUnits:s" +keys_d="step:d,startStep:d,endStep:d,stepRange:d,stepUnits:s" + +${tools_dir}/grib_set -s stepUnits=m,stepRange=60-120 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "60 m 60 m" +grib_check_key_equals $temp "-p $keys_s" "2 1 2 1-2 h" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "120m 60m 120m 60m-120m m" +${tools_dir}/grib_set -s stepRange=60m-120m $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "1 h 1 h" +grib_check_key_equals $temp "-p $keys_s" "2 1 2 1-2 h" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "120m 60m 120m 60m-120m m" #### CHECK units -fn="${data_dir}/reduced_gaussian_sub_area.grib2" +fn="$accumulated_field" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" ${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=96,indicatorOfUnitForTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" @@ -71,25 +111,21 @@ grib_check_key_equals $temp " -w count=1 -s stepUnits=12h -p step,stepUnits:s" " grib_check_key_equals $temp " -w count=1 -s stepUnits=D -p step,stepUnits:s" "4D D" ${tools_dir}/grib_set -s stepUnits=s,startStep=0,endStep=345600 $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +grib_check_key_equals $temp "-p $low_level_keys" "0 s 345600 s" ${tools_dir}/grib_set -s stepUnits=m,startStep=0,endStep=5760 $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" -${tools_dir}/grib_set -s stepUnits=15m,startStep=0,endStep=384 $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" -${tools_dir}/grib_set -s stepUnits=30m,startStep=0,endStep=192 $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +grib_check_key_equals $temp "-p $low_level_keys" "0 m 5760 m" ${tools_dir}/grib_set -s stepUnits=h,startStep=0,endStep=96 $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" ${tools_dir}/grib_set -s stepUnits=6h,startStep=0,endStep=16 $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +grib_check_key_equals $temp "-p $low_level_keys" "0 6h 16 6h" ${tools_dir}/grib_set -s stepUnits=12h,startStep=0,endStep=8 $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +grib_check_key_equals $temp "-p $low_level_keys" "0 12h 8 12h" ${tools_dir}/grib_set -s stepUnits=D,startStep=0,endStep=4 $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "0 h 96 h" +grib_check_key_equals $temp "-p $low_level_keys" "0 D 4 D" #### CHECK negative forecastTime -fn="${data_dir}/reduced_gaussian_sub_area.grib2" +fn="$accumulated_field" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" ${tools_dir}/grib_set -s forecastTime=-6,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=6,indicatorOfUnitForTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "-6 h 6 h" @@ -103,33 +139,36 @@ grib_check_key_equals $temp "-p stepRange" "-48" #### CHECK: check optimal units are set correctly in GRIB files -fn="${data_dir}/reduced_gaussian_sub_area.grib2" +fn="$accumulated_field" 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" ### TODO(maee): @Shahram: how to make parameters position independent ${tools_dir}/grib_set -s stepUnits:s=s,startStep:i=60,endStep:i=180 $temp $temp2 -grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" +grib_check_key_equals $temp2 "-p $low_level_keys" "60 s 120 s" #${tools_dir}/grib_set -s startStep:i=60,endStep:i=180,stepUnits:s=s $temp $temp2 #grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" +# Seconds ${tools_dir}/grib_set -s stepUnits:i=13,startStep:i=60,endStep:i=180 $temp $temp2 -grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" +grib_check_key_equals $temp2 "-p $low_level_keys" "60 s 120 s" ${tools_dir}/grib_set -s stepUnits:s=s,startStep:i=60,endStep:i=180 $temp $temp2 -grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 2 m" +grib_check_key_equals $temp2 "-p $low_level_keys" "60 s 120 s" +# Minutes ${tools_dir}/grib_set -s stepUnits:i=0,startStep:i=60,endStep:i=180 $temp $temp2 -grib_check_key_equals $temp2 "-p $low_level_keys" "1 h 2 h" +grib_check_key_equals $temp2 "-p $low_level_keys" "60 m 120 m" ${tools_dir}/grib_set -s stepUnits:s=m,startStep:i=60,endStep:i=180 $temp $temp2 -grib_check_key_equals $temp2 "-p $low_level_keys" "1 h 2 h" +grib_check_key_equals $temp2 "-p $low_level_keys" "60 m 120 m" +# Hours ${tools_dir}/grib_set -s stepUnits:i=1,startStep:i=60,endStep:i=180 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "60 h 120 h" ${tools_dir}/grib_set -s stepUnits:s=h,startStep:i=60,endStep:i=180 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "60 h 120 h" -#fn="${data_dir}/reduced_gaussian_sub_area.grib2" +#fn="$accumulated_field" #low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" ##high_level_keys="startStep:s,endStep:s" #high_level_keys="startStep:i,endStep:i" @@ -149,7 +188,7 @@ grib_check_key_equals $temp2 "-p $low_level_keys" "60 h 120 h" #exit #### CHECK: grib_set - endStep + stepUnits -fn="${data_dir}/reduced_gaussian_sub_area.grib2" +fn="$accumulated_field" 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" @@ -211,7 +250,7 @@ ${tools_dir}/grib_set -s stepRange:s=62D-122D $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "1488 h 1440 h" grib_check_key_equals $temp2 "-p stepRange:s" "1488-2928" -fn="${data_dir}/reduced_gaussian_surface.grib2" +fn="$instantaneous_field" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s" keys__="step,stepUnits:s" keys_s="step:s" @@ -221,16 +260,18 @@ keys_d="step:d,stepUnits:s" ${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "3540s s" grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "59m m" -#grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0" # TODO(maee): check behaviour (should be 0.983333) +#grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0" # not supported grib_check_key_equals $temp "-p $keys_s -s stepUnits=s" "3540s" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "59m" -#grib_check_key_equals $temp "-p $keys_s -F"%.2f" -s stepUnits=h" "0.983333" # TODO(maee): check behaviour // See tools for default output format +#grib_check_key_equals $temp "-p $keys_s -F"%.2f" -s stepUnits=h" "0.98" # not supported grib_check_key_equals $temp "-p $keys_i -s stepUnits=s" "3540 s" grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "59 m" -#grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0" # TODO(maee): check behaviour +#grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0" # not supported grib_check_key_equals $temp "-p $keys_d -s stepUnits=s" "3540 s" grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "59 m" -#grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0.983333" # TODO(maee): check behaviour +#grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0.983333" # not supported + + ${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m $fn $temp @@ -242,7 +283,8 @@ grib_check_key_equals $temp "-p $keys_d -s stepUnits=m" "0 m" grib_check_key_equals $temp "-p $keys_d -s stepUnits=h" "0 h" -fn="${data_dir}/reduced_gaussian_surface.grib2" + +fn="$instantaneous_field" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s" keys__="step,stepUnits:s" keys_s="step:s,stepUnits:s" @@ -308,13 +350,13 @@ grib_check_key_equals $temp "-p $keys_i" "24 h" grib_check_key_equals $temp "-p $keys_d" "24 h" -fn="${data_dir}/reduced_gaussian_sub_area.grib2" +fn="$accumulated_field" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" ${tools_dir}/grib_set -s stepRange=60m-2h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "1 h 1 h" -fn="${data_dir}/reduced_gaussian_sub_area.grib2" +fn="$accumulated_field" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" keys__="stepRange,startStep,endStep" keys_s="stepRange:s,startStep:s,endStep:s" From 1b05e403022c9db3f33c880f08d6a1aa0cddb9a2 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 29 Nov 2023 14:36:54 +0000 Subject: [PATCH 095/125] ECC-1620: Test stepunits key (MARS key) --- tests/grib_ecc-1620.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index b7a0449c7..bb91eb375 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -49,7 +49,7 @@ instantaneous_field=$data_dir/reduced_gaussian_surface.grib2 accumulated_field=$data_dir/reduced_gaussian_sub_area.grib2 # if stepUnits is set, then set the low level keys to stepUnits -# if stepUnits is not set, then optimise low level keys +# else optimise low level keys # instant fields: low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" fn="$instantaneous_field" @@ -59,6 +59,10 @@ keys_s="step:s" keys_i="step:i,stepUnits:s" keys_d="step:d,stepUnits:s" +${tools_dir}/grib_set -s stepunits=m,step=60 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "60 m" +grib_check_key_equals $temp "-p $keys_s" "1" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "60m" ${tools_dir}/grib_set -s stepUnits=m,step=60 $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m" grib_check_key_equals $temp "-p $keys_s" "1" @@ -77,6 +81,10 @@ keys_s="step:s,startStep:s,endStep:s,stepRange:s,stepUnits:s" keys_i="step:i,startStep:i,endStep:i,stepRange:i,stepUnits:s" keys_d="step:d,startStep:d,endStep:d,stepRange:d,stepUnits:s" +${tools_dir}/grib_set -s stepunits=m,stepRange=60-120 $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "60 m 60 m" +grib_check_key_equals $temp "-p $keys_s" "2 1 2 1-2 h" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "120m 60m 120m 60m-120m m" ${tools_dir}/grib_set -s stepUnits=m,stepRange=60-120 $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m 60 m" grib_check_key_equals $temp "-p $keys_s" "2 1 2 1-2 h" @@ -86,6 +94,7 @@ grib_check_key_equals $temp "-p $low_level_keys" "1 h 1 h" grib_check_key_equals $temp "-p $keys_s" "2 1 2 1-2 h" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "120m 60m 120m 60m-120m m" + #### CHECK units fn="$accumulated_field" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" From 8c7286d096f58528b2f87a7d23915083defba817 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 29 Nov 2023 14:56:48 +0000 Subject: [PATCH 096/125] ECC-1620: add future behaviour: export ECCODES_FUTURE_BEHAVIOUR=1 --- src/step.cc | 8 ++++- tests/grib_ecc-1620.sh | 74 ++++++++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/src/step.cc b/src/step.cc index d26a47128..6f7f2d045 100644 --- a/src/step.cc +++ b/src/step.cc @@ -191,8 +191,14 @@ std::string Step::value(const std::string& format) const { // // TODO(maee): Remove this code to enable future output, e.g., 15h. - if (unit_ != Unit::Value::HOUR) + int future_behaviour = getenv("ECCODES_FUTURE_BEHAVIOUR") ? atoi(getenv("ECCODES_FUTURE_BEHAVIOUR")) : 0; + if (future_behaviour != 1) { + if (unit_ != Unit::Value::HOUR) + u = unit_.value(); + } + else { u = unit_.value(); + } if (unit_ == Unit::Value::MINUTES15 || unit_ == Unit::Value::MINUTES30 || diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index bb91eb375..7987455ec 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -40,6 +40,8 @@ grib_check_key_equals() fi } +[[ -z "${ECCODES_FUTURE_BEHAVIOUR}" ]] && HOUR="" || HOUR="h" + label="grib_ecc-1620" temp=temp.$label temp2=temp_2.$label @@ -61,15 +63,16 @@ keys_d="step:d,stepUnits:s" ${tools_dir}/grib_set -s stepunits=m,step=60 $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m" -grib_check_key_equals $temp "-p $keys_s" "1" +grib_check_key_equals $temp "-p $keys_s" "1$HOUR" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "60m" ${tools_dir}/grib_set -s stepUnits=m,step=60 $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m" -grib_check_key_equals $temp "-p $keys_s" "1" +grib_check_key_equals $temp "-p $keys_s" "1$HOUR" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "60m" ${tools_dir}/grib_set -s step=60m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "1 h" -grib_check_key_equals $temp "-p $keys_s" "1" +grib_check_key_equals $temp "-p $low_level_keys" "1 h" +grib_check_key_equals $temp "-p $keys_s" "1$HOUR" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "60m" @@ -83,15 +86,15 @@ keys_d="step:d,startStep:d,endStep:d,stepRange:d,stepUnits:s" ${tools_dir}/grib_set -s stepunits=m,stepRange=60-120 $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m 60 m" -grib_check_key_equals $temp "-p $keys_s" "2 1 2 1-2 h" +grib_check_key_equals $temp "-p $keys_s" "2$HOUR 1$HOUR 2$HOUR 1$HOUR-2$HOUR h" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "120m 60m 120m 60m-120m m" ${tools_dir}/grib_set -s stepUnits=m,stepRange=60-120 $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m 60 m" -grib_check_key_equals $temp "-p $keys_s" "2 1 2 1-2 h" +grib_check_key_equals $temp "-p $keys_s" "2$HOUR 1$HOUR 2$HOUR 1$HOUR-2$HOUR h" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "120m 60m 120m 60m-120m m" ${tools_dir}/grib_set -s stepRange=60m-120m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "1 h 1 h" -grib_check_key_equals $temp "-p $keys_s" "2 1 2 1-2 h" +grib_check_key_equals $temp "-p $keys_s" "2$HOUR 1$HOUR 2$HOUR 1$HOUR-2$HOUR h" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "120m 60m 120m 60m-120m m" @@ -114,7 +117,7 @@ grib_check_key_equals $temp " -w count=1 -s stepUnits=s -p step,stepUnits:s" "34 grib_check_key_equals $temp " -w count=1 -s stepUnits=m -p step,stepUnits:s" "5760m m" grib_check_key_equals $temp " -w count=1 -s stepUnits=15m -p step,stepUnits:s" "384x15m 15m" grib_check_key_equals $temp " -w count=1 -s stepUnits=30m -p step,stepUnits:s" "192x30m 30m" -grib_check_key_equals $temp " -w count=1 -s stepUnits=h -p step,stepUnits:s" "96 h" +grib_check_key_equals $temp " -w count=1 -s stepUnits=h -p step,stepUnits:s" "96$HOUR h" grib_check_key_equals $temp " -w count=1 -s stepUnits=6h -p step,stepUnits:s" "16x6h 6h" grib_check_key_equals $temp " -w count=1 -s stepUnits=12h -p step,stepUnits:s" "8x12h 12h" grib_check_key_equals $temp " -w count=1 -s stepUnits=D -p step,stepUnits:s" "4D D" @@ -139,12 +142,12 @@ low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indi ${tools_dir}/grib_set -s forecastTime=-6,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=6,indicatorOfUnitForTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "-6 h 6 h" -grib_check_key_equals $temp "-s stepUnits:s=h -p startStep:s,endStep:s" "-6 0" +grib_check_key_equals $temp "-s stepUnits:s=h -p startStep:s,endStep:s" "-6$HOUR 0$HOUR" grib_check_key_equals $temp "-s stepUnits:s=m -p startStep:s,endStep:s" "-360m 0m" grib_check_key_equals $temp "-s stepUnits:s=s -p startStep:s,endStep:s" "-21600s 0s" ${tools_dir}/grib_set -s forecastTime=-48,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=0,indicatorOfUnitForTimeRange=h $fn $temp -grib_check_key_equals $temp "-p stepRange" "-48" +grib_check_key_equals $temp "-p stepRange" "-48$HOUR" #### CHECK: check optimal units are set correctly in GRIB files @@ -237,15 +240,15 @@ grib_check_key_equals $temp2 "-p $low_level_keys" "2 h 46 h" ${tools_dir}/grib_set -s stepRange:s=5h-30h $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "5 h 25 h" -grib_check_key_equals $temp2 "-p stepRange:s" "5-30" +grib_check_key_equals $temp2 "-p stepRange:s" "5$HOUR-30$HOUR" ${tools_dir}/grib_set -s stepRange:s=5-30 $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "5 h 25 h" -grib_check_key_equals $temp2 "-p stepRange:s" "5-30" +grib_check_key_equals $temp2 "-p stepRange:s" "5$HOUR-30$HOUR" ${tools_dir}/grib_set -s stepRange:s=60m-120m $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "1 h 1 h" -grib_check_key_equals $temp2 "-p stepRange:s" "1-2" +grib_check_key_equals $temp2 "-p stepRange:s" "1$HOUR-2$HOUR" ${tools_dir}/grib_set -s stepRange:s=60s-120s $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "1 m 1 m" @@ -257,7 +260,7 @@ grib_check_key_equals $temp2 "-p stepRange:s" "60m-121m" ${tools_dir}/grib_set -s stepRange:s=62D-122D $temp $temp2 grib_check_key_equals $temp2 "-p $low_level_keys" "1488 h 1440 h" -grib_check_key_equals $temp2 "-p stepRange:s" "1488-2928" +grib_check_key_equals $temp2 "-p stepRange:s" "1488$HOUR-2928$HOUR" fn="$instantaneous_field" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s" @@ -309,10 +312,10 @@ grib_check_key_equals $temp "-p $keys_d" "0 m" grib_check_key_equals $temp "-p $keys__ -s stepUnits=s" "0s s" grib_check_key_equals $temp "-p $keys__ -s stepUnits=m" "0m m" -grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0 h" +grib_check_key_equals $temp "-p $keys__ -s stepUnits=h" "0$HOUR h" grib_check_key_equals $temp "-p $keys_s -s stepUnits=s" "0s s" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "0m m" -grib_check_key_equals $temp "-p $keys_s -s stepUnits=h" "0 h" +grib_check_key_equals $temp "-p $keys_s -s stepUnits=h" "0$HOUR h" grib_check_key_equals $temp "-p $keys_i -s stepUnits=s" "0 s" grib_check_key_equals $temp "-p $keys_i -s stepUnits=m" "0 m" grib_check_key_equals $temp "-p $keys_i -s stepUnits=h" "0 h" @@ -331,8 +334,8 @@ grib_check_key_equals $temp "-p $keys_d" "59 m" ${tools_dir}/grib_set -s forecastTime=60,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m" -grib_check_key_equals $temp "-p $keys__" "1 h" -grib_check_key_equals $temp "-p $keys_s" "1 h" +grib_check_key_equals $temp "-p $keys__" "1$HOUR h" +grib_check_key_equals $temp "-p $keys_s" "1$HOUR h" grib_check_key_equals $temp "-p $keys_i" "1 h" grib_check_key_equals $temp "-p $keys_d" "1 h" @@ -346,15 +349,15 @@ grib_check_key_equals $temp "-p $keys_d" "61 m" ${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "24 h" -grib_check_key_equals $temp "-p $keys__" "24 h" -grib_check_key_equals $temp "-p $keys_s" "24 h" +grib_check_key_equals $temp "-p $keys__" "24$HOUR h" +grib_check_key_equals $temp "-p $keys_s" "24$HOUR h" grib_check_key_equals $temp "-p $keys_i" "24 h" grib_check_key_equals $temp "-p $keys_d" "24 h" ${tools_dir}/grib_set -s forecastTime=1440,indicatorOfUnitOfTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "1440 m" -grib_check_key_equals $temp "-p $keys__" "24 h" -grib_check_key_equals $temp "-p $keys_s" "24 h" +grib_check_key_equals $temp "-p $keys__" "24$HOUR h" +grib_check_key_equals $temp "-p $keys_s" "24$HOUR h" grib_check_key_equals $temp "-p $keys_i" "24 h" grib_check_key_equals $temp "-p $keys_d" "24 h" @@ -374,23 +377,22 @@ keys_d="stepRange:d,startStep:d,endStep:d" ${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=2,indicatorOfUnitForTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "0 m 2 h" -grib_check_key_equals $temp "-p $keys__" "0-2 0 2" -grib_check_key_equals $temp "-p $keys_s" "0-2 0 2" +grib_check_key_equals $temp "-p $keys__" "0$HOUR-2$HOUR 0$HOUR 2$HOUR" +grib_check_key_equals $temp "-p $keys_s" "0$HOUR-2$HOUR 0$HOUR 2$HOUR" grib_check_key_equals $temp "-p $keys_i" "2 0 2" grib_check_key_equals $temp "-p $keys_d" "2 0 2" ${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" -grib_check_key_equals $temp "-p $keys__" "24-48 24 48" -grib_check_key_equals $temp "-p $keys_s" "24-48 24 48" +grib_check_key_equals $temp "-p $keys__" "24$HOUR-48$HOUR 24$HOUR 48$HOUR" +grib_check_key_equals $temp "-p $keys_s" "24$HOUR-48$HOUR 24$HOUR 48$HOUR" grib_check_key_equals $temp "-p $keys_i" "48 24 48" grib_check_key_equals $temp "-p $keys_d" "48 24 48" ${tools_dir}/grib_set -s forecastTime=25,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=1,indicatorOfUnitForTimeRange=D $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "25 h 1 D" -grib_check_key_equals $temp "-p $keys__" "25-49 25 49" -grib_check_key_equals $temp "-p $keys__" "25-49 25 49" -grib_check_key_equals $temp "-p $keys_s" "25-49 25 49" +grib_check_key_equals $temp "-p $keys__" "25$HOUR-49$HOUR 25$HOUR 49$HOUR" +grib_check_key_equals $temp "-p $keys_s" "25$HOUR-49$HOUR 25$HOUR 49$HOUR" grib_check_key_equals $temp "-p $keys_i" "49 25 49" grib_check_key_equals $temp "-p $keys_d" "49 25 49" @@ -404,29 +406,29 @@ grib_check_key_equals $temp "-p $keys_d" "60 45 60" ${tools_dir}/grib_set -s forecastTime=60,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=2,indicatorOfUnitForTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m 2 h" -grib_check_key_equals $temp "-p $keys__" "1-3 1 3" -grib_check_key_equals $temp "-p $keys_s" "1-3 1 3" +grib_check_key_equals $temp "-p $keys__" "1$HOUR-3$HOUR 1$HOUR 3$HOUR" +grib_check_key_equals $temp "-p $keys_s" "1$HOUR-3$HOUR 1$HOUR 3$HOUR" grib_check_key_equals $temp "-p $keys_i" "3 1 3" grib_check_key_equals $temp "-p $keys_d" "3 1 3" ${tools_dir}/grib_set -s forecastTime=18,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=6,indicatorOfUnitForTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "18 h 6 h" -grib_check_key_equals $temp "-p $keys__" "18-24 18 24" -grib_check_key_equals $temp "-p $keys_s" "18-24 18 24" +grib_check_key_equals $temp "-p $keys__" "18$HOUR-24$HOUR 18$HOUR 24$HOUR" +grib_check_key_equals $temp "-p $keys_s" "18$HOUR-24$HOUR 18$HOUR 24$HOUR" grib_check_key_equals $temp "-p $keys_i" "24 18 24" grib_check_key_equals $temp "-p $keys_d" "24 18 24" ${tools_dir}/grib_set -s forecastTime=1080,indicatorOfUnitOfTimeRange=m,lengthOfTimeRange=360,indicatorOfUnitForTimeRange=m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "1080 m 360 m" -grib_check_key_equals $temp "-p $keys__" "18-24 18 24" -grib_check_key_equals $temp "-p $keys_s" "18-24 18 24" +grib_check_key_equals $temp "-p $keys__" "18$HOUR-24$HOUR 18$HOUR 24$HOUR" +grib_check_key_equals $temp "-p $keys_s" "18$HOUR-24$HOUR 18$HOUR 24$HOUR" grib_check_key_equals $temp "-p $keys_i" "24 18 24" grib_check_key_equals $temp "-p $keys_d" "24 18 24" ${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" -grib_check_key_equals $temp "-p $keys__" "18-24 18 24" -grib_check_key_equals $temp "-p $keys_s" "18-24 18 24" +grib_check_key_equals $temp "-p $keys__" "18$HOUR-24$HOUR 18$HOUR 24$HOUR" +grib_check_key_equals $temp "-p $keys_s" "18$HOUR-24$HOUR 18$HOUR 24$HOUR" grib_check_key_equals $temp "-p $keys_i" "24 18 24" grib_check_key_equals $temp "-p $keys_d" "24 18 24" From f155dbbb58d1ef9ba167be6d3fc2556336b8d5ec Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Thu, 30 Nov 2023 20:25:43 +0000 Subject: [PATCH 097/125] codes_get_all_codetable_entries_malloc --- src/eccodes_prototypes.h | 1 + src/grib_accessor_class_codetable.cc | 47 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/eccodes_prototypes.h b/src/eccodes_prototypes.h index c9032e08e..26a6d0851 100644 --- a/src/eccodes_prototypes.h +++ b/src/eccodes_prototypes.h @@ -340,6 +340,7 @@ void grib_smart_table_delete(grib_context* c); /* grib_accessor_class_codetable.cc*/ void grib_codetable_delete(grib_context* c); +int codes_get_all_codetable_entries_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries); /* grib_accessor_class_codetable_units.cc*/ diff --git a/src/grib_accessor_class_codetable.cc b/src/grib_accessor_class_codetable.cc index e8e286623..6ecafa05a 100644 --- a/src/grib_accessor_class_codetable.cc +++ b/src/grib_accessor_class_codetable.cc @@ -523,6 +523,53 @@ void grib_codetable_delete(grib_context* c) } } +int codes_get_all_codetable_entries_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries) +{ + long lvalue = 0; + size_t size = 1; + int err = 0; + grib_context* c = h->context; + + grib_accessor* aa = grib_find_accessor(h, key); + if (!aa) return GRIB_NOT_FOUND; + + if (!STR_EQUAL(aa->cclass->name, "codetable")) { + return GRIB_INVALID_ARGUMENT; // key is not a codetable + } + + const grib_accessor_codetable* ca = (const grib_accessor_codetable*)aa; // could be dynamic_cast + + if ((err = grib_unpack_long(aa, &lvalue, &size)) != GRIB_SUCCESS) { + return err; + } + + const grib_codetable* table = ca->table; + if (!table) return GRIB_INTERNAL_ERROR; + + grib_codetable* cached_table = c->codetable; + while (cached_table) { + if (STR_EQUAL(table->recomposed_name[0], cached_table->recomposed_name[0])) { + // Found a cache entry that matches the recomposed name of ours + *entries = (code_table_entry*)calloc(cached_table->size, sizeof(code_table_entry)); + if (!*entries) { + return GRIB_OUT_OF_MEMORY; + } + size_t n = 0; + for (size_t i = 0; i < cached_table->size; i++) { + const char* abbrev = cached_table->entries[i].abbreviation; + if (abbrev) { + (*entries)[n++] = cached_table->entries[i]; + } + } + *num_entries = n; + return GRIB_SUCCESS; + } + cached_table = cached_table->next; + } + + return GRIB_CODE_NOT_FOUND_IN_TABLE; +} + static void dump(grib_accessor* a, grib_dumper* dumper) { grib_accessor_codetable* self = (grib_accessor_codetable*)a; From 832ca298e200f9407dba2d924633d448b0206bdf Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 1 Dec 2023 09:21:17 +0000 Subject: [PATCH 098/125] ECC-1620: Change ECCODES_FUTURE_BEHAVIOUR to ECCODES_GRIB_SHOW_HOUR_STEPUNIT --- src/grib_accessor_class_g2end_step.cc | 6 ++++-- src/grib_accessor_class_g2step_range.cc | 8 +++++--- src/grib_accessor_class_step_in_units.cc | 3 ++- src/grib_api_internal.h | 1 + src/grib_context.cc | 4 ++++ src/step.cc | 13 +++++-------- src/step.h | 2 +- 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 0bd8d70ab..b7ae986f3 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -540,6 +540,7 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en long typeOfTimeIncrement; double dend, dstep; + int show_hours = a->context->show_hour_stepunit; Step end_step{end_step_value, end_step_unit}; @@ -587,7 +588,7 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if (time_range.value() < 0) { grib_context_log(h->context, GRIB_LOG_ERROR, - "endStep < startStep (%s < %s)", end_step.value("%g").c_str(), start_step.value("%g").c_str()); + "endStep < startStep (%s < %s)", end_step.value("%g", show_hours).c_str(), start_step.value("%g", show_hours).c_str()); return GRIB_WRONG_STEP; } @@ -651,6 +652,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) size_t step_len = 0; long step_value; long step_units; + int show_hours = a->context->show_hour_stepunit; if ((ret = unpack_long(a, &step_value, &step_len)) != GRIB_SUCCESS) return ret; @@ -665,7 +667,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) std::stringstream ss; - ss << step.value(fp_format); + ss << step.value(fp_format, show_hours); size_t size = ss.str().size() + 1; diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 1260f44c2..c0bcc209d 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -142,6 +142,8 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) double end_step_value = 0; long step_units; + int show_hours = a->context->show_hour_stepunit; + if ((ret = grib_get_double_internal(h, self->start_step, &start_step_value)) != GRIB_SUCCESS) return ret; if ((ret= grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) @@ -160,7 +162,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) Step start_step{start_step_value, step_units}; if (self->end_step == NULL) { - ss << start_step.value(fp_format); + ss << start_step.value(fp_format, show_hours); } else { if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) @@ -169,10 +171,10 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) Step end_step{end_step_value, step_units}; if (start_step_value == end_step_value) { - ss << end_step.value(fp_format); + ss << end_step.value(fp_format, show_hours); } else { - ss << start_step.value(fp_format) << "-" << end_step.value(fp_format); + ss << start_step.value(fp_format, show_hours) << "-" << end_step.value(fp_format, show_hours); } } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index b7faa5859..d1ebcd832 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -312,6 +312,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) long step_units; char fp_format[128] = "%g"; size_t fp_format_len = sizeof(fp_format); + int show_hours = a->context->show_hour_stepunit; if ((ret = grib_get_long_internal(h, "startStep", &start_step_value)) != GRIB_SUCCESS) return ret; @@ -326,7 +327,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) Step step{start_step_value, start_step_unit}; std::stringstream ss; - ss << step.value(fp_format); + ss << step.value(fp_format, show_hours); size_t size = ss.str().size() + 1; diff --git a/src/grib_api_internal.h b/src/grib_api_internal.h index bf6b3694d..177214a6c 100644 --- a/src/grib_api_internal.h +++ b/src/grib_api_internal.h @@ -1005,6 +1005,7 @@ struct grib_context int no_big_group_split; int no_spd; int keep_matrix; + int show_hour_stepunit; char* grib_definition_files_path; char* grib_samples_path; char* grib_concept_path; diff --git a/src/grib_context.cc b/src/grib_context.cc index 8f52633eb..d77fd2c06 100644 --- a/src/grib_context.cc +++ b/src/grib_context.cc @@ -287,6 +287,7 @@ static grib_context default_grib_context = { 0, /* no_big_group_split */ 0, /* no_spd */ 0, /* keep_matrix */ + 0, /* show_hour_stepunit */ 0, /* grib_definition_files_path */ 0, /* grib_samples_path */ 0, /* grib_concept_path */ @@ -388,6 +389,7 @@ grib_context* grib_context_get_default() const char* no_big_group_split = NULL; const char* no_spd = NULL; const char* keep_matrix = NULL; + const char* show_hour_stepunit = NULL; const char* bufrdc_mode = NULL; const char* bufr_set_to_missing_if_out_of_range = NULL; const char* bufr_multi_element_constant_arrays = NULL; @@ -415,6 +417,7 @@ grib_context* grib_context_get_default() no_big_group_split = codes_getenv("ECCODES_GRIB_NO_BIG_GROUP_SPLIT"); no_spd = codes_getenv("ECCODES_GRIB_NO_SPD"); keep_matrix = codes_getenv("ECCODES_GRIB_KEEP_MATRIX"); + show_hour_stepunit = codes_getenv("ECCODES_GRIB_SHOW_HOUR_STEPUNIT"); file_pool_max_opened_files = getenv("ECCODES_FILE_POOL_MAX_OPENED_FILES"); /* On UNIX, when we read from a file we get exactly what is in the file on disk. @@ -429,6 +432,7 @@ grib_context* grib_context_get_default() default_grib_context.no_big_group_split = no_big_group_split ? atoi(no_big_group_split) : 0; default_grib_context.no_spd = no_spd ? atoi(no_spd) : 0; default_grib_context.keep_matrix = keep_matrix ? atoi(keep_matrix) : 1; + default_grib_context.show_hour_stepunit = show_hour_stepunit ? atoi(show_hour_stepunit) : 0; default_grib_context.write_on_fail = write_on_fail ? atoi(write_on_fail) : 0; default_grib_context.no_abort = no_abort ? atoi(no_abort) : 0; default_grib_context.debug = debug ? atoi(debug) : 0; diff --git a/src/step.cc b/src/step.cc index 6f7f2d045..49a61f662 100644 --- a/src/step.cc +++ b/src/step.cc @@ -180,7 +180,7 @@ Step& Step::optimize_unit() } template <> -std::string Step::value(const std::string& format) const { +std::string Step::value(const std::string& format, bool show_hours) const { constexpr int MAX_SIZE = 128; char output[MAX_SIZE]; std::string u; @@ -188,16 +188,13 @@ std::string Step::value(const std::string& format) const { // Do not print unit if it is HOUR to keep backward compatibility // with previous versions of ecCodes (see ECC-1620). This is a temporary solution. - // - // TODO(maee): Remove this code to enable future output, e.g., 15h. - int future_behaviour = getenv("ECCODES_FUTURE_BEHAVIOUR") ? atoi(getenv("ECCODES_FUTURE_BEHAVIOUR")) : 0; - if (future_behaviour != 1) { - if (unit_ != Unit::Value::HOUR) - u = unit_.value(); + if (show_hours) { + u = unit_.value(); } else { - u = unit_.value(); + if (unit_ != Unit::Value::HOUR) + u = unit_.value(); } if (unit_ == Unit::Value::MINUTES15 || diff --git a/src/step.h b/src/step.h index 79afdaeb1..a9dbf8bca 100644 --- a/src/step.h +++ b/src/step.h @@ -42,7 +42,7 @@ public: // Getters template T value() const; template T value(const Unit& unit) const; - template T value(const std::string& format) const; + template T value(const std::string& format, bool show_hours) const; Unit unit() const { return unit_; } // Setters From 5b74d558a2bbf47464f6535378b1a9c31261d75d Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 1 Dec 2023 09:23:21 +0000 Subject: [PATCH 099/125] ECC-1620: Change ECCODES_FUTURE_BEHAVIOUR to ECCODES_GRIB_SHOW_HOUR_STEPUNIT --- tests/grib_ecc-1620.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 7987455ec..eb3bfb573 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -40,7 +40,7 @@ grib_check_key_equals() fi } -[[ -z "${ECCODES_FUTURE_BEHAVIOUR}" ]] && HOUR="" || HOUR="h" +[[ -z "${ECCODES_GRIB_SHOW_HOUR_STEPUNIT}" ]] && HOUR="" || HOUR="h" label="grib_ecc-1620" temp=temp.$label From 33d8f6eeafe5201dc170db13cf7c93f228c9cbc3 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 1 Dec 2023 09:31:31 +0000 Subject: [PATCH 100/125] ECC-1620: Fix ECCODES_GRIB_SHOW_HOUR_STEPUNIT --- tests/grib_ecc-1620.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index eb3bfb573..0d2994459 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -40,7 +40,7 @@ grib_check_key_equals() fi } -[[ -z "${ECCODES_GRIB_SHOW_HOUR_STEPUNIT}" ]] && HOUR="" || HOUR="h" +[ -v ECCODES_GRIB_SHOW_HOUR_STEPUNIT ] && HOUR="h" || HOUR="" label="grib_ecc-1620" temp=temp.$label From d2ef5965afe07c9be89ced8ec11b7ff451c6093c Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Fri, 1 Dec 2023 12:46:07 +0000 Subject: [PATCH 101/125] ECC-1620: Fix broken Windows test (ECCODES_FUTURE_BEHAVIOUR: unbound variable) --- tests/grib_ecc-1620.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 7987455ec..1fdf6b075 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -40,7 +40,9 @@ grib_check_key_equals() fi } +set +u [[ -z "${ECCODES_FUTURE_BEHAVIOUR}" ]] && HOUR="" || HOUR="h" +set -u label="grib_ecc-1620" temp=temp.$label From 61695712e14e2fb58f504da8148a5d8030d7a4a9 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 1 Dec 2023 12:51:22 +0000 Subject: [PATCH 102/125] ECC-1620: nai --- tests/grib_ecc-1620.sh | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 0d2994459..40dc6516a 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -50,6 +50,24 @@ samples_dir=$ECCODES_SAMPLES_PATH instantaneous_field=$data_dir/reduced_gaussian_surface.grib2 accumulated_field=$data_dir/reduced_gaussian_sub_area.grib2 + +#### Check that step, stepRange, startStep, endStep produce the same result in instantaneous fields +fn="$instantaneous_field" +low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s" +keys_step="step,step:s,step:i,step:d,stepUnits:s" +keys_step_range="stepRange,stepRange:s,stepRange:i,stepRange:d,stepUnits:s" +keys_start_step="startStep,startStep:s,startStep:i,startStep:d,stepUnits:s" +keys_end_step="endStep,endStep:s,endStep:i,endStep:d,stepUnits:s" +${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 m" +${tools_dir}/grib_set -s stepunits=m,step=59 $fn $temp +grib_check_key_equals $temp "-p $keys_step" "59m 59m 59 59 m" +grib_check_key_equals $temp "-p $keys_step_range" "59m 59m 59 59 m" +grib_check_key_equals $temp "-p $keys_start_step" "59m 59m 59 59 m" +grib_check_key_equals $temp "-p $keys_end_step" "59m 59m 59 59 m" + + + # if stepUnits is set, then set the low level keys to stepUnits # else optimise low level keys # instant fields: @@ -71,7 +89,6 @@ grib_check_key_equals $temp "-p $keys_s" "1$HOUR" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "60m" ${tools_dir}/grib_set -s step=60m $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "1 h" -grib_check_key_equals $temp "-p $low_level_keys" "1 h" grib_check_key_equals $temp "-p $keys_s" "1$HOUR" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "60m" From 511270e75c2fedfc95d87afe7b2d3d4a5379431f Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 1 Dec 2023 13:12:04 +0000 Subject: [PATCH 103/125] ECC-1620: Check value of ECCODES_GRIB_SHOW_HOUR_STEPUNIT --- tests/grib_ecc-1620.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index 40dc6516a..ecabcb1fd 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -40,7 +40,12 @@ grib_check_key_equals() fi } -[ -v ECCODES_GRIB_SHOW_HOUR_STEPUNIT ] && HOUR="h" || HOUR="" +HOUR="" +if [ -v ECCODES_GRIB_SHOW_HOUR_STEPUNIT ]; then + if [ $ECCODES_GRIB_SHOW_HOUR_STEPUNIT -gt 0 ]; then + export HOUR="h" + fi +fi label="grib_ecc-1620" temp=temp.$label From 52205dc77d237d57b2948951c19bd3afb3f4bdbc Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Fri, 1 Dec 2023 16:26:54 +0000 Subject: [PATCH 104/125] ECC-1620: Set startStepUnit --- src/grib_accessor_class_g2end_step.cc | 1 + tests/grib_ecc-1620.sh | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index b7ae986f3..62b0c9e26 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -546,6 +546,7 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en /*point in time */ if (self->year == NULL) { + err = grib_set_long_internal(h, "startStepUnit", end_step.unit().value()); err = grib_set_long_internal(h, self->start_step_value, end_step.value()); return err; } diff --git a/tests/grib_ecc-1620.sh b/tests/grib_ecc-1620.sh index ecabcb1fd..bcf149ead 100755 --- a/tests/grib_ecc-1620.sh +++ b/tests/grib_ecc-1620.sh @@ -41,12 +41,13 @@ grib_check_key_equals() } HOUR="" -if [ -v ECCODES_GRIB_SHOW_HOUR_STEPUNIT ]; then +if (set -u; : ${ECCODES_GRIB_SHOW_HOUR_STEPUNIT?}) 2> /dev/null; then if [ $ECCODES_GRIB_SHOW_HOUR_STEPUNIT -gt 0 ]; then export HOUR="h" fi fi + label="grib_ecc-1620" temp=temp.$label temp2=temp_2.$label @@ -56,24 +57,32 @@ instantaneous_field=$data_dir/reduced_gaussian_surface.grib2 accumulated_field=$data_dir/reduced_gaussian_sub_area.grib2 -#### Check that step, stepRange, startStep, endStep produce the same result in instantaneous fields +#### Make sure that step, stepRange, startStep, endStep produce the same result for instantaneous fields fn="$instantaneous_field" low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s" keys_step="step,step:s,step:i,step:d,stepUnits:s" keys_step_range="stepRange,stepRange:s,stepRange:i,stepRange:d,stepUnits:s" keys_start_step="startStep,startStep:s,startStep:i,startStep:d,stepUnits:s" keys_end_step="endStep,endStep:s,endStep:i,endStep:d,stepUnits:s" -${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m $fn $temp -grib_check_key_equals $temp "-p $low_level_keys" "0 m" +${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=h $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 h" ${tools_dir}/grib_set -s stepunits=m,step=59 $fn $temp grib_check_key_equals $temp "-p $keys_step" "59m 59m 59 59 m" grib_check_key_equals $temp "-p $keys_step_range" "59m 59m 59 59 m" grib_check_key_equals $temp "-p $keys_start_step" "59m 59m 59 59 m" grib_check_key_equals $temp "-p $keys_end_step" "59m 59m 59 59 m" +${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=h $fn $temp +grib_check_key_equals $temp "-p $low_level_keys" "0 h" +${tools_dir}/grib_set -s step=59m $fn $temp +grib_check_key_equals $temp "-p $keys_step" "59m 59m 59 59 m" +grib_check_key_equals $temp "-p $keys_step_range" "59m 59m 59 59 m" +grib_check_key_equals $temp "-p $keys_start_step" "59m 59m 59 59 m" +grib_check_key_equals $temp "-p $keys_end_step" "59m 59m 59 59 m" -# if stepUnits is set, then set the low level keys to stepUnits +#### stepUnits overrides the units in the low level keys +# if stepUnits=UNIT is set, then set the low level keys to UNIT # else optimise low level keys # instant fields: low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s" From dca34cfc2df5e418d2c8265a213cc59650e70e24 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Sat, 2 Dec 2023 16:34:56 +0000 Subject: [PATCH 105/125] codes_get_codetable_contents_malloc: Renamed and added test --- src/eccodes_prototypes.h | 2 +- src/grib_accessor_class_codetable.cc | 2 +- tests/CMakeLists.txt | 2 ++ tests/codes_codetable.cc | 35 ++++++++++++++++++++++++++++ tests/codes_codetable.sh | 22 +++++++++++++++++ 5 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 tests/codes_codetable.cc create mode 100755 tests/codes_codetable.sh diff --git a/src/eccodes_prototypes.h b/src/eccodes_prototypes.h index 26a6d0851..a68f0f343 100644 --- a/src/eccodes_prototypes.h +++ b/src/eccodes_prototypes.h @@ -340,7 +340,7 @@ void grib_smart_table_delete(grib_context* c); /* grib_accessor_class_codetable.cc*/ void grib_codetable_delete(grib_context* c); -int codes_get_all_codetable_entries_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries); +int codes_get_codetable_contents_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries); /* grib_accessor_class_codetable_units.cc*/ diff --git a/src/grib_accessor_class_codetable.cc b/src/grib_accessor_class_codetable.cc index 6ecafa05a..cccb573dd 100644 --- a/src/grib_accessor_class_codetable.cc +++ b/src/grib_accessor_class_codetable.cc @@ -523,7 +523,7 @@ void grib_codetable_delete(grib_context* c) } } -int codes_get_all_codetable_entries_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries) +int codes_get_codetable_contents_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries) { long lvalue = 0; size_t size = 1; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 55818b054..8079b9082 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -50,6 +50,7 @@ list(APPEND test_c_bins codes_set_samples_path codes_compare_keys codes_dump_content + codes_codetable grib_sh_ieee64 grib_ieee grib_set_bytes @@ -243,6 +244,7 @@ if( HAVE_BUILD_TOOLS ) grib_set_force bufr_ecc-556 codes_ecc-1698 + codes_codetable gts_get gts_ls gts_count diff --git a/tests/codes_codetable.cc b/tests/codes_codetable.cc new file mode 100644 index 000000000..36b36f98a --- /dev/null +++ b/tests/codes_codetable.cc @@ -0,0 +1,35 @@ +/* + * (C) Copyright 2005- ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * + * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by + * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. + */ +#include +#include "grib_api_internal.h" + +#undef NDEBUG +#include + +int main(int argc, char* argv[]) +{ + Assert(argc == 1); + grib_handle* h = grib_handle_new_from_samples(0, "GRIB2"); + + code_table_entry* entries = NULL; + size_t num_entries = 0; + const char* keyname = "indicatorOfUnitOfTimeRange"; + int err = codes_get_codetable_contents_malloc(h, keyname, &entries, &num_entries); + Assert(!err); + Assert(num_entries == 13); + + for (size_t i=0; i Date: Sat, 2 Dec 2023 17:45:44 +0000 Subject: [PATCH 106/125] codes_codetable_check_entry and further tests --- src/eccodes_prototypes.h | 3 +- src/grib_accessor_class_codetable.cc | 35 ++++++++++++++++------ tests/codes_codetable.cc | 43 +++++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 13 deletions(-) diff --git a/src/eccodes_prototypes.h b/src/eccodes_prototypes.h index a68f0f343..59e5958d4 100644 --- a/src/eccodes_prototypes.h +++ b/src/eccodes_prototypes.h @@ -340,7 +340,8 @@ void grib_smart_table_delete(grib_context* c); /* grib_accessor_class_codetable.cc*/ void grib_codetable_delete(grib_context* c); -int codes_get_codetable_contents_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries); +int codes_codetable_get_contents_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries); +int codes_codetable_check_entry(const grib_handle* h, const char* key, long code); /* grib_accessor_class_codetable_units.cc*/ diff --git a/src/grib_accessor_class_codetable.cc b/src/grib_accessor_class_codetable.cc index cccb573dd..e1df1b87f 100644 --- a/src/grib_accessor_class_codetable.cc +++ b/src/grib_accessor_class_codetable.cc @@ -523,7 +523,7 @@ void grib_codetable_delete(grib_context* c) } } -int codes_get_codetable_contents_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries) +int codes_codetable_get_contents_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries) { long lvalue = 0; size_t size = 1; @@ -539,6 +539,7 @@ int codes_get_codetable_contents_malloc(const grib_handle* h, const char* key, c const grib_accessor_codetable* ca = (const grib_accessor_codetable*)aa; // could be dynamic_cast + // Decode the key itself. This will either fetch it from the cache or place it there if ((err = grib_unpack_long(aa, &lvalue, &size)) != GRIB_SUCCESS) { return err; } @@ -546,22 +547,18 @@ int codes_get_codetable_contents_malloc(const grib_handle* h, const char* key, c const grib_codetable* table = ca->table; if (!table) return GRIB_INTERNAL_ERROR; - grib_codetable* cached_table = c->codetable; + grib_codetable* cached_table = c->codetable; // Access the codetable cache while (cached_table) { if (STR_EQUAL(table->recomposed_name[0], cached_table->recomposed_name[0])) { // Found a cache entry that matches the recomposed name of ours + *num_entries = cached_table->size; *entries = (code_table_entry*)calloc(cached_table->size, sizeof(code_table_entry)); if (!*entries) { return GRIB_OUT_OF_MEMORY; } - size_t n = 0; for (size_t i = 0; i < cached_table->size; i++) { - const char* abbrev = cached_table->entries[i].abbreviation; - if (abbrev) { - (*entries)[n++] = cached_table->entries[i]; - } + (*entries)[i] = cached_table->entries[i]; } - *num_entries = n; return GRIB_SUCCESS; } cached_table = cached_table->next; @@ -570,6 +567,28 @@ int codes_get_codetable_contents_malloc(const grib_handle* h, const char* key, c return GRIB_CODE_NOT_FOUND_IN_TABLE; } +int codes_codetable_check_entry(const grib_handle* h, const char* key, long code) +{ + code_table_entry* entries = NULL; + size_t num_entries = 0; + int err = 0; + err = codes_codetable_get_contents_malloc(h, key, &entries, &num_entries); + if (err) return err; + + if (code < 0 || (size_t)code >= num_entries) { + err = GRIB_OUT_OF_RANGE; + goto cleanup; + } + + if (entries[code].abbreviation == NULL) { + err = GRIB_INVALID_KEY_VALUE; + goto cleanup; + } +cleanup: + free(entries); + return err; +} + static void dump(grib_accessor* a, grib_dumper* dumper) { grib_accessor_codetable* self = (grib_accessor_codetable*)a; diff --git a/tests/codes_codetable.cc b/tests/codes_codetable.cc index 36b36f98a..65ee7a1da 100644 --- a/tests/codes_codetable.cc +++ b/tests/codes_codetable.cc @@ -20,15 +20,50 @@ int main(int argc, char* argv[]) code_table_entry* entries = NULL; size_t num_entries = 0; - const char* keyname = "indicatorOfUnitOfTimeRange"; - int err = codes_get_codetable_contents_malloc(h, keyname, &entries, &num_entries); + int err = codes_codetable_get_contents_malloc(h, "indicatorOfUnitOfTimeRange", &entries, &num_entries); Assert(!err); - Assert(num_entries == 13); + Assert(entries != NULL); + Assert(num_entries == 256); for (size_t i=0; i Date: Sat, 2 Dec 2023 18:35:01 +0000 Subject: [PATCH 107/125] Functions codes_codetable_check_code_figure and codes_codetable_check_abbreviation --- src/eccodes_prototypes.h | 3 ++- src/grib_accessor_class_codetable.cc | 24 +++++++++++++++++++++++- tests/codes_codetable.cc | 24 +++++++++++++++++------- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/eccodes_prototypes.h b/src/eccodes_prototypes.h index 59e5958d4..1d049c14c 100644 --- a/src/eccodes_prototypes.h +++ b/src/eccodes_prototypes.h @@ -341,7 +341,8 @@ void grib_smart_table_delete(grib_context* c); /* grib_accessor_class_codetable.cc*/ void grib_codetable_delete(grib_context* c); int codes_codetable_get_contents_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries); -int codes_codetable_check_entry(const grib_handle* h, const char* key, long code); +int codes_codetable_check_code_figure(const grib_handle* h, const char* key, long code); +int codes_codetable_check_abbreviation(const grib_handle* h, const char* key, const char* abbreviation); /* grib_accessor_class_codetable_units.cc*/ diff --git a/src/grib_accessor_class_codetable.cc b/src/grib_accessor_class_codetable.cc index e1df1b87f..92f5daf5f 100644 --- a/src/grib_accessor_class_codetable.cc +++ b/src/grib_accessor_class_codetable.cc @@ -567,7 +567,7 @@ int codes_codetable_get_contents_malloc(const grib_handle* h, const char* key, c return GRIB_CODE_NOT_FOUND_IN_TABLE; } -int codes_codetable_check_entry(const grib_handle* h, const char* key, long code) +int codes_codetable_check_code_figure(const grib_handle* h, const char* key, long code) { code_table_entry* entries = NULL; size_t num_entries = 0; @@ -589,6 +589,28 @@ cleanup: return err; } +int codes_codetable_check_abbreviation(const grib_handle* h, const char* key, const char* abbreviation) +{ + code_table_entry* entries = NULL; + size_t num_entries = 0; + int err = 0; + err = codes_codetable_get_contents_malloc(h, key, &entries, &num_entries); + if (err) return err; + + bool found = false; + for (size_t i=0; i Date: Sat, 2 Dec 2023 18:51:39 +0000 Subject: [PATCH 108/125] Codetable API functions --- src/eccodes_prototypes.h | 2 +- src/grib_accessor_class_codetable.cc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/eccodes_prototypes.h b/src/eccodes_prototypes.h index 1d049c14c..6d72509de 100644 --- a/src/eccodes_prototypes.h +++ b/src/eccodes_prototypes.h @@ -341,7 +341,7 @@ void grib_smart_table_delete(grib_context* c); /* grib_accessor_class_codetable.cc*/ void grib_codetable_delete(grib_context* c); int codes_codetable_get_contents_malloc(const grib_handle* h, const char* key, code_table_entry** entries, size_t* num_entries); -int codes_codetable_check_code_figure(const grib_handle* h, const char* key, long code); +int codes_codetable_check_code_figure(const grib_handle* h, const char* key, long code_figure); int codes_codetable_check_abbreviation(const grib_handle* h, const char* key, const char* abbreviation); /* grib_accessor_class_codetable_units.cc*/ diff --git a/src/grib_accessor_class_codetable.cc b/src/grib_accessor_class_codetable.cc index 92f5daf5f..f57917858 100644 --- a/src/grib_accessor_class_codetable.cc +++ b/src/grib_accessor_class_codetable.cc @@ -567,7 +567,7 @@ int codes_codetable_get_contents_malloc(const grib_handle* h, const char* key, c return GRIB_CODE_NOT_FOUND_IN_TABLE; } -int codes_codetable_check_code_figure(const grib_handle* h, const char* key, long code) +int codes_codetable_check_code_figure(const grib_handle* h, const char* key, long code_figure) { code_table_entry* entries = NULL; size_t num_entries = 0; @@ -575,12 +575,12 @@ int codes_codetable_check_code_figure(const grib_handle* h, const char* key, lon err = codes_codetable_get_contents_malloc(h, key, &entries, &num_entries); if (err) return err; - if (code < 0 || (size_t)code >= num_entries) { + if (code_figure < 0 || (size_t)code_figure >= num_entries) { err = GRIB_OUT_OF_RANGE; goto cleanup; } - if (entries[code].abbreviation == NULL) { + if (entries[code_figure].abbreviation == NULL) { err = GRIB_INVALID_KEY_VALUE; goto cleanup; } From e3ba4f1a0274ffdc86eb9ebf38feb170be1fe76e Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Sun, 3 Dec 2023 12:28:41 +0000 Subject: [PATCH 109/125] Rename test --- tests/CMakeLists.txt | 2 +- tests/{grib_ecc-1620.sh => grib_sub_hourly.sh} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/{grib_ecc-1620.sh => grib_sub_hourly.sh} (100%) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 69cf59a5f..59c46bc02 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -240,7 +240,7 @@ if( HAVE_BUILD_TOOLS ) grib_ecc-1397 grib_ecc-1425 grib_ecc-1467 - grib_ecc-1620 + grib_sub_hourly grib_set_bytes grib_set_force bufr_ecc-556 diff --git a/tests/grib_ecc-1620.sh b/tests/grib_sub_hourly.sh similarity index 100% rename from tests/grib_ecc-1620.sh rename to tests/grib_sub_hourly.sh From 89dda0d8459ebec2182b40ac851b011f970cde6c Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Sun, 3 Dec 2023 12:31:04 +0000 Subject: [PATCH 110/125] Rename test --- tests/grib_sub_hourly.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/grib_sub_hourly.sh b/tests/grib_sub_hourly.sh index bcf149ead..c9ac1f34e 100755 --- a/tests/grib_sub_hourly.sh +++ b/tests/grib_sub_hourly.sh @@ -10,6 +10,9 @@ . ./include.ctest.sh +# See JIRA issues ECC-1620, ECC-1238 +# ----------------------------------- + grib_expect_failure() { a_file=$1 From 6109f790e8ece64e5b9bd18686df1875613c2d22 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 6 Dec 2023 10:18:05 +0000 Subject: [PATCH 111/125] ECC-1620: Revert mars.step data type back to string --- tools/grib_tools.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/grib_tools.cc b/tools/grib_tools.cc index 2ad3bef83..b039c8d0d 100644 --- a/tools/grib_tools.cc +++ b/tools/grib_tools.cc @@ -755,9 +755,6 @@ static void grib_tools_set_print_keys(grib_runtime_options* options, grib_handle if (strlen(name) > options->default_print_width) options->default_print_width = (int)strlen(name); options->print_keys[options->print_keys_count].type = GRIB_TYPE_STRING; - if (strcmp(ns, "mars") == 0 && (strcmp(name, "step") == 0)) { - options->print_keys[options->print_keys_count].type = GRIB_TYPE_LONG; - } // For the statistics namespace, do not force the type to be string. // Setting it to undefined will use the keys' native type i.e. GRIB_TYPE_DOUBLE if (strcmp(ns,"statistics")==0) From f414dc41de8284de79b048b36ae1e9d49068d479 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 6 Dec 2023 11:58:50 +0000 Subject: [PATCH 112/125] ECC-1620: Remove time.stepunits and mars.stepunits --- definitions/grib1/section.1.def | 2 +- definitions/grib2/products_s2s.def | 2 +- definitions/grib2/template.4.forecast_time.def | 6 +----- definitions/grib2/template.4.localtime.def | 2 +- definitions/grib2/template.4.point_in_time.def | 3 +-- definitions/grib2/template.4.statistical.def | 2 +- tests/grib_ecc-1212.sh | 1 - tests/grib_mars_keys1.sh | 2 -- 8 files changed, 6 insertions(+), 14 deletions(-) diff --git a/definitions/grib1/section.1.def b/definitions/grib1/section.1.def index 1178f969d..fcb306cb5 100644 --- a/definitions/grib1/section.1.def +++ b/definitions/grib1/section.1.def @@ -222,7 +222,7 @@ alias ls.stepRange = stepRange; alias ls.dataDate = dataDate; alias mars.step = endStep; -alias mars.stepunits = stepUnits; +alias stepunits = stepUnits; alias mars.date = dataDate; alias mars.levtype = indicatorOfTypeOfLevel; alias mars.time = dataTime; diff --git a/definitions/grib2/products_s2s.def b/definitions/grib2/products_s2s.def index 09238eb49..7063def51 100644 --- a/definitions/grib2/products_s2s.def +++ b/definitions/grib2/products_s2s.def @@ -73,7 +73,7 @@ alias mars.type = marsType; # Normally MARS step is endStep but for monthly means we want stepRange if (stepType is "avg") { alias mars.step = stepRange; - alias mars.stepunits = stepUnits; + alias stepunits = stepUnits; } if (isHindcast == 1) { diff --git a/definitions/grib2/template.4.forecast_time.def b/definitions/grib2/template.4.forecast_time.def index 2f05d0cb8..8dc62f16b 100644 --- a/definitions/grib2/template.4.forecast_time.def +++ b/definitions/grib2/template.4.forecast_time.def @@ -12,12 +12,8 @@ alias minutesAfterReferenceTimeOfDataCutoff=minutesAfterDataCutoff; codetable[1] indicatorOfUnitOfTimeRange ('4.4.table',masterDir,localDir) : dump; alias indicatorOfUnitForForecastTime = indicatorOfUnitOfTimeRange; -#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) : transient,dump; -transient startStepUnit = 255 : hidden; +transient startStepUnit = 255 : hidden; # 255 means MISSING. See code table 4.4 transient endStepUnit = 255 : hidden; # Forecast time in units defined by previous octet (GRIB-29: supports negative forecast time) diff --git a/definitions/grib2/template.4.localtime.def b/definitions/grib2/template.4.localtime.def index f37c5c3aa..3432f8b6a 100644 --- a/definitions/grib2/template.4.localtime.def +++ b/definitions/grib2/template.4.localtime.def @@ -82,7 +82,7 @@ if (numberOfForecastsUsedInLocalTime == 1) { alias mars.date = dateOfForecastUsedInLocalTime : dump; alias mars.time = timeOfForecastUsedInLocalTime : dump; alias mars.step = endStep; - alias mars.stepunits = stepUnits; + alias stepunits = stepUnits; alias time.dataDate = dateOfForecastUsedInLocalTime; alias time.dataTime = timeOfForecastUsedInLocalTime; alias time.endStep = endStep; diff --git a/definitions/grib2/template.4.point_in_time.def b/definitions/grib2/template.4.point_in_time.def index f32d04ba1..3e341f54b 100644 --- a/definitions/grib2/template.4.point_in_time.def +++ b/definitions/grib2/template.4.point_in_time.def @@ -7,7 +7,7 @@ alias step=startStep; alias marsStep=startStep; alias mars.step=startStep; -alias mars.stepunits=stepUnits; +alias stepunits=stepUnits; alias marsStartStep = startStep; alias marsEndStep = endStep; @@ -21,7 +21,6 @@ meta stepHumanReadable step_human_readable(stepUnits, stepRange): hidden,no_copy alias time.stepType=stepType; alias time.stepRange=stepRange; -alias time.stepunits=stepUnits; alias time.dataDate=dataDate; alias time.dataTime=dataTime; alias time.startStep=startStep; diff --git a/definitions/grib2/template.4.statistical.def b/definitions/grib2/template.4.statistical.def index 6a8688fdd..fa40bbd37 100644 --- a/definitions/grib2/template.4.statistical.def +++ b/definitions/grib2/template.4.statistical.def @@ -112,7 +112,7 @@ if (numberOfTimeRanges == 1 || numberOfTimeRanges == 2) { alias ls.stepRange=stepRange; alias mars.step=endStep; -alias mars.stepunits=stepUnits; +alias stepunits=stepUnits; alias time.stepType=stepType; alias time.stepRange=stepRange; diff --git a/tests/grib_ecc-1212.sh b/tests/grib_ecc-1212.sh index f52026594..7ae426756 100755 --- a/tests/grib_ecc-1212.sh +++ b/tests/grib_ecc-1212.sh @@ -59,7 +59,6 @@ cat > $tempRef < $tempRef << EOF "class": "od", "type": "an", "stream": "oper", - "stepunits": "h", "step": 0, "levelist": 1000, "levtype": "pl", @@ -69,7 +68,6 @@ cat > $tempRef << EOF "class": "od", "type": "pf", "stream": "enfo", - "stepunits": "h", "step": 0, "levelist": 1000, "levtype": "pl", From 5bd9d6264202052fe44f86ab128584cdecf004c2 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Wed, 6 Dec 2023 15:58:51 +0000 Subject: [PATCH 113/125] ECC-1620: Introduction of the "eccodes" namespace --- src/grib_accessor_class_g2end_step.cc | 48 +++++++++---------- src/grib_accessor_class_g2step_range.cc | 30 ++++++------ src/grib_accessor_class_optimal_step_units.cc | 24 +++++----- src/grib_accessor_class_step_in_units.cc | 34 ++++++------- src/step.cc | 4 ++ src/step.h | 3 ++ src/step_unit.cc | 4 ++ src/step_unit.h | 4 ++ src/step_utilities.cc | 6 +-- src/step_utilities.h | 4 +- 10 files changed, 88 insertions(+), 73 deletions(-) diff --git a/src/grib_accessor_class_g2end_step.cc b/src/grib_accessor_class_g2end_step.cc index 62b0c9e26..e967268ef 100644 --- a/src/grib_accessor_class_g2end_step.cc +++ b/src/grib_accessor_class_g2end_step.cc @@ -214,8 +214,8 @@ static int convert_time_range_long_( Assert(lengthOfTimeRange != NULL); if (indicatorOfUnitForTimeRange != stepUnits) { - Step time_range{*lengthOfTimeRange, indicatorOfUnitForTimeRange}; - time_range.set_unit(Unit{stepUnits}); + eccodes::Step time_range{*lengthOfTimeRange, indicatorOfUnitForTimeRange}; + time_range.set_unit(eccodes::Unit{stepUnits}); if (time_range.value() != time_range.value()) { return GRIB_DECODING_ERROR; } @@ -297,8 +297,8 @@ static int unpack_one_time_range_double_(grib_accessor* a, double *val , size_t* if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement))) return err; - Step start_step{start_step_value, start_step_unit}; - Step time_range{time_range_value, time_range_unit}; + eccodes::Step start_step{start_step_value, start_step_unit}; + eccodes::Step time_range{time_range_value, time_range_unit}; if (typeOfTimeIncrement == 1) { /* See GRIB-488 */ @@ -309,10 +309,10 @@ static int unpack_one_time_range_double_(grib_accessor* a, double *val , size_t* } } if (add_time_range) { - *val = (start_step + time_range).value(Unit(step_units)); + *val = (start_step + time_range).value(eccodes::Unit(step_units)); } else { - *val = start_step.value(Unit(start_step_unit)); + *val = start_step.value(eccodes::Unit(start_step_unit)); } return GRIB_SUCCESS; @@ -392,7 +392,7 @@ static int unpack_multiple_time_ranges_double_(grib_accessor* a, double* val, si if ((err = grib_get_long_internal(h, "startStepUnit", &start_step_unit))) return err; - Step start_step{start_step_value, start_step_unit}; + eccodes::Step start_step{start_step_value, start_step_unit}; if ((err = grib_get_long_internal(h, self->step_units, &step_units))) return err; @@ -420,8 +420,8 @@ static int unpack_multiple_time_ranges_double_(grib_accessor* a, double* val, si long the_coded_unit = arr_coded_unit[i]; long the_coded_time_range = arr_coded_time_range[i]; - Step time_range{the_coded_unit, the_coded_time_range}; - *val = (start_step + time_range).value(Unit(step_units)); + eccodes::Step time_range{the_coded_unit, the_coded_time_range}; + *val = (start_step + time_range).value(eccodes::Unit(step_units)); return GRIB_SUCCESS; } @@ -542,7 +542,7 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en double dend, dstep; int show_hours = a->context->show_hour_stepunit; - Step end_step{end_step_value, end_step_unit}; + eccodes::Step end_step{end_step_value, end_step_unit}; /*point in time */ if (self->year == NULL) { @@ -575,7 +575,7 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if ((err= grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) return err; - if (Unit{start_step_unit} == Unit{Unit::Value::MISSING}) { + if (eccodes::Unit{start_step_unit} == eccodes::Unit{eccodes::Unit::Value::MISSING}) { grib_context_log(h->context, GRIB_LOG_ERROR, "missing start step unit"); return GRIB_WRONG_STEP_UNIT; @@ -584,8 +584,8 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement))) return err; - Step start_step{start_step_value, start_step_unit}; - Step time_range = end_step - start_step; + eccodes::Step start_step{start_step_value, start_step_unit}; + eccodes::Step time_range = end_step - start_step; if (time_range.value() < 0) { grib_context_log(h->context, GRIB_LOG_ERROR, @@ -597,7 +597,7 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en if (err != GRIB_SUCCESS) return err; - dstep = end_step.value(Unit{Unit::Value::DAY}); + dstep = end_step.value(eccodes::Unit{eccodes::Unit::Value::DAY}); dend += dstep; err = grib_julian_to_datetime(dend, &year_of_end_of_interval, &month_of_end_of_interval, @@ -621,14 +621,14 @@ static int pack_long_(grib_accessor* a, const long end_step_value, const long en const char* forecast_time_value_key = "forecastTime"; const char* forecast_time_unit_key = "indicatorOfUnitOfTimeRange"; - Step forecast_time_opt; - Step time_range_opt; - if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { + eccodes::Step forecast_time_opt; + eccodes::Step time_range_opt; + if (eccodes::Unit{force_step_units} == eccodes::Unit{eccodes::Unit::Value::MISSING}) { std::tie(forecast_time_opt, time_range_opt) = find_common_units(start_step.optimize_unit(), time_range.optimize_unit()); } else { - forecast_time_opt = Step{start_step.value(Unit{force_step_units}), Unit{force_step_units}}; - time_range_opt = Step{time_range.value(Unit{force_step_units}), Unit{force_step_units}}; + forecast_time_opt = eccodes::Step{start_step.value(eccodes::Unit{force_step_units}), eccodes::Unit{force_step_units}}; + time_range_opt = eccodes::Step{time_range.value(eccodes::Unit{force_step_units}), eccodes::Unit{force_step_units}}; } if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range_opt.value())) != GRIB_SUCCESS) @@ -663,7 +663,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; try { - Step step(step_value, step_units); + eccodes::Step step(step_value, step_units); step.set_unit(step_units); std::stringstream ss; @@ -698,12 +698,12 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) try { long end_step_unit; - if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { + if (eccodes::Unit{force_step_units} == eccodes::Unit{eccodes::Unit::Value::MISSING}) { if ((ret = grib_get_long_internal(h, "endStepUnit", &end_step_unit)) != GRIB_SUCCESS) return ret; - if (Unit{end_step_unit} == Unit{Unit::Value::MISSING}) - end_step_unit = Unit{Unit::Value::HOUR}.value(); + if (eccodes::Unit{end_step_unit} == eccodes::Unit{eccodes::Unit::Value::MISSING}) + end_step_unit = eccodes::Unit{eccodes::Unit::Value::HOUR}.value(); } else { end_step_unit = force_step_units; @@ -726,7 +726,7 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) return ret; try { - Step end_step = step_from_string(val, Unit{force_step_units}); + eccodes::Step end_step = step_from_string(val, eccodes::Unit{force_step_units}); end_step.optimize_unit(); if ((ret = grib_set_long_internal(h, "endStepUnit", end_step.unit().value())) != GRIB_SUCCESS) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index c0bcc209d..2089f493b 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -149,7 +149,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) if ((ret= grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; try { - if (Unit{step_units} == Unit{Unit::Value::MISSING}) { + if (eccodes::Unit{step_units} == eccodes::Unit{eccodes::Unit::Value::MISSING}) { if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; } @@ -160,7 +160,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; std::stringstream ss; - Step start_step{start_step_value, step_units}; + eccodes::Step start_step{start_step_value, step_units}; if (self->end_step == NULL) { ss << start_step.value(fp_format, show_hours); } @@ -168,7 +168,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) return ret; - Step end_step{end_step_value, step_units}; + eccodes::Step end_step{end_step_value, step_units}; if (start_step_value == end_step_value) { ss << end_step.value(fp_format, show_hours); @@ -206,24 +206,24 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) return ret; try { - std::vector steps = parse_range(val, Unit{force_step_units}); + std::vector steps = parse_range(val, eccodes::Unit{force_step_units}); if (steps.size() == 0) { grib_context_log(a->context, GRIB_LOG_ERROR, "Could not parse step range: %s", val); return GRIB_INVALID_ARGUMENT; } - Step step_0; - Step step_1; - if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { + eccodes::Step step_0; + eccodes::Step step_1; + if (eccodes::Unit{force_step_units} == eccodes::Unit{eccodes::Unit::Value::MISSING}) { if (steps.size() > 1) std::tie(step_0, step_1) = find_common_units(steps[0].optimize_unit(), steps[1].optimize_unit()); else step_0 = steps[0].optimize_unit(); } else { - step_0 = Step{steps[0].value(Unit{force_step_units}), Unit{force_step_units}}; + step_0 = eccodes::Step{steps[0].value(eccodes::Unit{force_step_units}), eccodes::Unit{force_step_units}}; if (steps.size() > 1) { - step_1 = Step{steps[1].value(Unit{force_step_units}), Unit{force_step_units}}; + step_1 = eccodes::Step{steps[1].value(eccodes::Unit{force_step_units}), eccodes::Unit{force_step_units}}; } } @@ -281,19 +281,19 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) try { if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) throw std::runtime_error("Failed to get stepUnits"); - if (Unit{step_units} == Unit{Unit::Value::MISSING}) { + if (eccodes::Unit{step_units} == eccodes::Unit{eccodes::Unit::Value::MISSING}) { if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; } - Step start_step{end_start_value, step_units}; + eccodes::Step start_step{end_start_value, step_units}; if (self->end_step == NULL) { *val = start_step.value(); } else { if ((ret = grib_get_long_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) return ret; - Step end_step{end_step_value, step_units}; + eccodes::Step end_step{end_step_value, step_units}; *val = end_step.value(); } } @@ -321,19 +321,19 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) throw std::runtime_error("Failed to get stepUnits"); try { - if (Unit{step_units} == Unit{Unit::Value::MISSING}) { + if (eccodes::Unit{step_units} == eccodes::Unit{eccodes::Unit::Value::MISSING}) { if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS) return ret; } - Step start_step{end_start_value, step_units}; + eccodes::Step start_step{end_start_value, step_units}; if (self->end_step == NULL) { *val = start_step.value(); } else { if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS) return ret; - Step end_step{end_step_value, step_units}; + eccodes::Step end_step{end_step_value, step_units}; *val = end_step.value(); } } diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 5d297b96c..7ac95a902 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -137,24 +137,24 @@ static size_t string_length(grib_accessor* a) return 255; } -static long staticStepUnits = Unit{Unit::Value::MISSING}.value(); -static long staticForceStepUnits = Unit{Unit::Value::MISSING}.value(); +static long staticStepUnits = eccodes::Unit{eccodes::Unit::Value::MISSING}.value(); +static long staticForceStepUnits = eccodes::Unit{eccodes::Unit::Value::MISSING}.value(); static int pack_long(grib_accessor* a, const long* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); - auto supported_units = Unit::list_supported_units(); + auto supported_units = eccodes::Unit::list_supported_units(); try { - Unit unit{*val}; // throws if not supported + eccodes::Unit unit{*val}; // throws if not supported auto iter = std::find(supported_units.begin(), supported_units.end(), unit); if (iter == supported_units.end()) { - throw std::runtime_error{"Unit not supported"}; + throw std::runtime_error{"eccodes::Unit not supported"}; } } catch (std::exception& e) { std::string supported_units_str; for (auto& u : supported_units) - supported_units_str += Unit{u}.value() + ","; + supported_units_str += eccodes::Unit{u}.value() + ","; supported_units_str.pop_back(); std::string msg = std::string{"Invalid unit: "} + std::to_string(*val) + " (" + e.what() + ")" + ". Available units are: " + supported_units_str; @@ -174,7 +174,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) static int unpack_long(grib_accessor* a, long* val, size_t* len) { try { - if (Unit{staticStepUnits} != Unit{Unit::Value::MISSING}) { + if (eccodes::Unit{staticStepUnits} != eccodes::Unit{eccodes::Unit::Value::MISSING}) { *val = staticStepUnits; return GRIB_SUCCESS; } @@ -196,7 +196,7 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) *val = time_range_opt.value().optimize_unit().unit().value(); } else if (!forecast_time_opt && !time_range_opt) { - *val = Unit{Unit::Value::HOUR}.value(); + *val = eccodes::Unit{eccodes::Unit::Value::HOUR}.value(); } } catch (std::exception& e) { @@ -210,14 +210,14 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { try { - long unit = Unit{val}.value(); + long unit = eccodes::Unit{val}.value(); pack_long(a, &unit, len); } catch (std::exception& e) { - auto supported_units = Unit::list_supported_units(); + auto supported_units = eccodes::Unit::list_supported_units(); std::string supported_units_str; for (auto& u : supported_units) - supported_units_str += Unit{u}.value() + ","; + supported_units_str += eccodes::Unit{u}.value() + ","; supported_units_str.pop_back(); std::string msg = "Invalid unit: " + std::string(val) + " (" + e.what() + ")" + ". Available units are: " + supported_units_str; @@ -235,7 +235,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) size_t unit_len = 0; if ((ret = unpack_long(a, &unit, &unit_len)) != GRIB_SUCCESS) return ret; - *len = snprintf(val, *len, "%s", Unit{unit}.value().c_str()); + *len = snprintf(val, *len, "%s", eccodes::Unit{unit}.value().c_str()); return GRIB_SUCCESS; } diff --git a/src/grib_accessor_class_step_in_units.cc b/src/grib_accessor_class_step_in_units.cc index d1ebcd832..b6800f6fb 100644 --- a/src/grib_accessor_class_step_in_units.cc +++ b/src/grib_accessor_class_step_in_units.cc @@ -152,13 +152,13 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) return err; try { - Step step{forecast_time_value, forecast_time_unit}; + eccodes::Step step{forecast_time_value, forecast_time_unit}; step.optimize_unit(); - if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.value())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(h, "startStepUnit", eccodes::Unit{step_units}.value())) != GRIB_SUCCESS) return err; - *val = step.value(Unit{step_units}); + *val = step.value(eccodes::Unit{step_units}); } catch (std::exception& e) { grib_context_log(h->context, GRIB_LOG_ERROR, "step_in_units: %s", e.what()); @@ -183,12 +183,12 @@ static int unpack_double(grib_accessor* a, double * val, size_t* len) return err; try { - Step step{forecast_time_value, forecast_time_unit}; + eccodes::Step step{forecast_time_value, forecast_time_unit}; - if ((err = grib_set_long_internal(h, "startStepUnit", Unit{step_units}.value())) != GRIB_SUCCESS) + if ((err = grib_set_long_internal(h, "startStepUnit", eccodes::Unit{step_units}.value())) != GRIB_SUCCESS) return err; - *val = step.value(Unit{step_units}); + *val = step.value(eccodes::Unit{step_units}); } catch (std::exception& e) { grib_context_log(h->context, GRIB_LOG_ERROR, "step_in_units: %s", e.what()); @@ -215,9 +215,9 @@ static int pack_long_new_(grib_accessor* a, const long start_step_value, const l if ((err = grib_get_long_internal(h, "startStepUnit", &start_step_unit_old)) != GRIB_SUCCESS) return err; - Step start_step_old(start_step_value_old, start_step_unit_old); - Step forecast_time(start_step_value, start_step_unit); - Step time_range_new{}; + eccodes::Step start_step_old(start_step_value_old, start_step_unit_old); + eccodes::Step forecast_time(start_step_value, start_step_unit); + eccodes::Step time_range_new{}; auto time_range_opt = get_step(h, self->time_range_value, self->time_range_unit); @@ -225,7 +225,7 @@ static int pack_long_new_(grib_accessor* a, const long start_step_value, const l auto time_range = time_range_opt.value(); time_range = time_range - (forecast_time - start_step_old); if (time_range.value() < 0) - time_range = Step{0l, time_range.unit()}; + time_range = eccodes::Step{0l, time_range.unit()}; auto [sa, sb] = find_common_units(forecast_time.optimize_unit(), time_range.optimize_unit()); if ((err = set_step(h, self->forecast_time_value, self->forecast_time_unit, sa)) != GRIB_SUCCESS) return err; @@ -236,7 +236,7 @@ static int pack_long_new_(grib_accessor* a, const long start_step_value, const l return GRIB_SUCCESS; } - if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { + if (eccodes::Unit{force_step_units} == eccodes::Unit{eccodes::Unit::Value::MISSING}) { forecast_time.optimize_unit(); } @@ -259,12 +259,12 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) long start_step_unit; try { - if (Unit{force_step_units} == Unit{Unit::Value::MISSING}) { + if (eccodes::Unit{force_step_units} == eccodes::Unit{eccodes::Unit::Value::MISSING}) { if ((ret = grib_get_long_internal(h, "startStepUnit", &start_step_unit)) != GRIB_SUCCESS) return ret; - if (Unit{start_step_unit} == Unit{Unit::Value::MISSING}) - start_step_unit = Unit{Unit::Value::HOUR}.value(); + if (eccodes::Unit{start_step_unit} == eccodes::Unit{eccodes::Unit::Value::MISSING}) + start_step_unit = eccodes::Unit{eccodes::Unit::Value::HOUR}.value(); } else { start_step_unit = force_step_units; @@ -283,14 +283,14 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) static int pack_string(grib_accessor* a, const char* val, size_t* len) { grib_handle* h = grib_handle_of_accessor(a); - //long force_step_units = Unit(Unit::Value::MISSING).value(); + //long force_step_units = eccodes::Unit(eccodes::Unit::Value::MISSING).value(); int ret = GRIB_SUCCESS; long force_step_units; if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) return ret; try { - Step step = step_from_string(val, Unit{force_step_units}); + eccodes::Step step = step_from_string(val, eccodes::Unit{force_step_units}); if ((ret = pack_long_new_(a, step.value(), step.unit().value(), force_step_units)) != GRIB_SUCCESS) return ret; } @@ -324,7 +324,7 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return ret; try { - Step step{start_step_value, start_step_unit}; + eccodes::Step step{start_step_value, start_step_unit}; std::stringstream ss; ss << step.value(fp_format, show_hours); diff --git a/src/step.cc b/src/step.cc index 49a61f662..81bdaeeb3 100644 --- a/src/step.cc +++ b/src/step.cc @@ -20,6 +20,8 @@ #include "step_unit.h" #include "step.h" +namespace eccodes { + Step step_from_string(const std::string& step, const Unit& force_unit) { std::regex re("([0-9.]+)([smhDMYC]?)"); @@ -214,3 +216,5 @@ std::string Step::value(const std::string& format, bool show_hours) } return output; } + +} // namespace eccodes diff --git a/src/step.h b/src/step.h index a9dbf8bca..a7d8b2bd1 100644 --- a/src/step.h +++ b/src/step.h @@ -24,6 +24,7 @@ #include "step_unit.h" +namespace eccodes { class Step { public: // Constructors @@ -122,3 +123,5 @@ template T Step::value(const Unit& unit) const { T value = from_seconds(seconds, unit); return value; } + +} // namespace eccodes diff --git a/src/step_unit.cc b/src/step_unit.cc index e356d4ba4..bd192a6e7 100644 --- a/src/step_unit.cc +++ b/src/step_unit.cc @@ -10,6 +10,8 @@ #include "step_unit.h" +namespace eccodes { + Unit::Map Unit::map_{}; std::vector Unit::grib_selected_units = { @@ -47,3 +49,5 @@ template <> Unit::Value Unit::value() const { template <> std::string Unit::value() const { return map_.unit_to_name(internal_value_); } + +} // namespace eccodes diff --git a/src/step_unit.h b/src/step_unit.h index 4bfd23290..3d8897bbe 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -18,6 +18,8 @@ #include #include +namespace eccodes { + template using Minutes = std::chrono::duration>; template using Hours = std::chrono::duration>; template using Days = std::chrono::duration>; @@ -232,3 +234,5 @@ T from_seconds(Seconds seconds, const Unit& unit) { } return value; } + +} // namespace eccodes diff --git a/src/step_utilities.cc b/src/step_utilities.cc index dcf0d3dd5..4ae82a911 100644 --- a/src/step_utilities.cc +++ b/src/step_utilities.cc @@ -11,7 +11,7 @@ #include "step_utilities.h" #include -std::optional get_step(grib_handle* h, const char* value_key, const char* unit_key) +std::optional get_step(grib_handle* h, const char* value_key, const char* unit_key) { if (value_key && unit_key && grib_is_defined(h, unit_key) && grib_is_defined(h, value_key)) { long unit = 0; @@ -22,14 +22,14 @@ std::optional get_step(grib_handle* h, const char* value_key, const char* if (grib_get_long_internal(h, value_key, &value) != GRIB_SUCCESS) return {}; - return Step(value, unit); + return eccodes::Step(value, unit); } else { return {}; } } -int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step) +int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const eccodes::Step& step) { int err; if ((err = grib_set_long_internal(h, value_key.c_str(), step.value())) != GRIB_SUCCESS) diff --git a/src/step_utilities.h b/src/step_utilities.h index 8224a3a32..9ae26996d 100644 --- a/src/step_utilities.h +++ b/src/step_utilities.h @@ -14,5 +14,5 @@ #include "step.h" #include -std::optional get_step(grib_handle* h, const char* value_key, const char* unit_key); -int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step); +std::optional get_step(grib_handle* h, const char* value_key, const char* unit_key); +int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const eccodes::Step& step); From 3c1c9df9a0f09f451be091a68408463d61b42ad0 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Tue, 2 Jan 2024 14:12:58 +0000 Subject: [PATCH 114/125] Sub-hourly: Add stepUnits to the time namespace for instantaneous fields --- definitions/grib2/template.4.point_in_time.def | 1 + 1 file changed, 1 insertion(+) diff --git a/definitions/grib2/template.4.point_in_time.def b/definitions/grib2/template.4.point_in_time.def index 3e341f54b..7e188b230 100644 --- a/definitions/grib2/template.4.point_in_time.def +++ b/definitions/grib2/template.4.point_in_time.def @@ -21,6 +21,7 @@ meta stepHumanReadable step_human_readable(stepUnits, stepRange): hidden,no_copy alias time.stepType=stepType; alias time.stepRange=stepRange; +alias time.stepUnits=stepUnits; alias time.dataDate=dataDate; alias time.dataTime=dataTime; alias time.startStep=startStep; From 87f34c24b880ec1e6b153c87a1547c16faaf2a3a Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Sat, 13 Jan 2024 14:52:25 +0000 Subject: [PATCH 115/125] Testing: Sub-hourly with grib_filter (needs fixing - see src/grib_accessor_class_optimal_step_units.cc) --- src/grib_accessor_class_g2step_range.cc | 2 +- tests/grib_sub_hourly.sh | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 2089f493b..e15d195f3 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -44,8 +44,8 @@ or edit "accessor.class" and rerun ./make_class.pl static int get_native_type(grib_accessor*); 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_long(grib_accessor*, long* val, 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*); diff --git a/tests/grib_sub_hourly.sh b/tests/grib_sub_hourly.sh index c9ac1f34e..37799249e 100755 --- a/tests/grib_sub_hourly.sh +++ b/tests/grib_sub_hourly.sh @@ -51,9 +51,10 @@ if (set -u; : ${ECCODES_GRIB_SHOW_HOUR_STEPUNIT?}) 2> /dev/null; then fi -label="grib_ecc-1620" -temp=temp.$label -temp2=temp_2.$label +label="grib_sub_hourly" +temp=temp.1.$label +temp2=temp.2.$label +tempFilt=temp.$label.filt samples_dir=$ECCODES_SAMPLES_PATH instantaneous_field=$data_dir/reduced_gaussian_surface.grib2 @@ -466,7 +467,20 @@ grib_check_key_equals $temp "-p $keys_s" "18$HOUR-24$HOUR 18$HOUR 24$HOUR" grib_check_key_equals $temp "-p $keys_i" "24 18 24" grib_check_key_equals $temp "-p $keys_d" "24 18 24" -rm -f $temp $temp2 +cat >$tempFilt<$tempFilt< Date: Mon, 15 Jan 2024 10:57:50 +0000 Subject: [PATCH 116/125] Fix time interval setting for instantenous fields --- src/grib_accessor_class_g2step_range.cc | 46 +++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 2089f493b..6a67342ac 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -13,6 +13,7 @@ #include "step_utilities.h" #include #include +#include /* This is used by make_class.pl @@ -195,11 +196,45 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return GRIB_SUCCESS; } +//static int pack_string(grib_accessor* a, const char* val, size_t* len) +//{ +// grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; +// grib_handle* h = grib_handle_of_accessor(a); + +// long start = 0, theEnd = -1; +// int ret = 0; +// char *p = NULL, *q = NULL; + +// start = strtol(val, &p, 10); +// theEnd = start; + +// if (*p != 0) +// theEnd = strtol(++p, &q, 10); +// ret = grib_set_long_internal(h, self->startStep, start); +// if (ret) +// return ret; + +// if (self->endStep != NULL) { +// ret = grib_set_long_internal(h, self->endStep, theEnd); +// if (ret) +// return ret; +// } + +// return 0; +//} + + + +// Step range format: [-] +// and can be in different units +// stepRange="0" in instantaneous field is equivalent to set step=0 +// stepRange="0" in accumulated field is equivalent to ??? static int pack_string(grib_accessor* a, const char* 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; + std::cerr << "VAL: " << val << std::endl; long force_step_units; if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) @@ -232,11 +267,16 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) if ((ret = set_step(h, "forecastTime" , "indicatorOfUnitOfTimeRange", step_0)) != GRIB_SUCCESS) return ret; - if ((self->end_step != NULL) && (steps.size() > 1)) { + if (self->end_step != NULL) { if ((ret = grib_set_long_internal(h, "endStepUnit", step_1.unit().value()))) return ret; - if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) - return ret; + if (steps.size() > 1) { + if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) + return ret; + } else { + if ((ret = grib_set_long_internal(h, self->end_step, step_0.value()))) + return ret; + } } } catch (std::exception& e) { From 7d27cc45cc94339141ab52587b8ca8724c14b4dc Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Mon, 15 Jan 2024 11:01:36 +0000 Subject: [PATCH 117/125] Compiler warnings: unreferenced local variable e --- src/step_unit.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/step_unit.h b/src/step_unit.h index 3d8897bbe..bd078f403 100644 --- a/src/step_unit.h +++ b/src/step_unit.h @@ -20,21 +20,21 @@ namespace eccodes { -template using Minutes = std::chrono::duration>; -template using Hours = std::chrono::duration>; -template using Days = std::chrono::duration>; -template using Months = std::chrono::duration>; -template using Years = std::chrono::duration>; -template using Years10 = std::chrono::duration>; -template using Years30 = std::chrono::duration>; +template using Minutes = std::chrono::duration>; +template using Hours = std::chrono::duration>; +template using Days = std::chrono::duration>; +template using Months = std::chrono::duration>; +template using Years = std::chrono::duration>; +template using Years10 = std::chrono::duration>; +template using Years30 = std::chrono::duration>; template using Centuries = std::chrono::duration>; -template using Hours3 = std::chrono::duration>; -template using Hours6 = std::chrono::duration>; -template using Hours12 = std::chrono::duration>; -template using Seconds = std::chrono::duration>; +template using Hours3 = std::chrono::duration>; +template using Hours6 = std::chrono::duration>; +template using Hours12 = std::chrono::duration>; +template using Seconds = std::chrono::duration>; template using Minutes15 = std::chrono::duration>; template using Minutes30 = std::chrono::duration>; -template using Missing = std::chrono::duration>; +template using Missing = std::chrono::duration>; @@ -70,7 +70,7 @@ public: try { internal_value_ = map_.name_to_unit(unit_value); } catch (std::exception& e) { - throw std::runtime_error(std::string{"Unit not found"}); + throw std::runtime_error(std::string{"Unit not found "} + e.what()); } } @@ -78,7 +78,7 @@ public: try { internal_value_ = map_.long_to_unit(unit_value); } catch (std::exception& e) { - throw std::runtime_error(std::string{"Unit not found"}); + throw std::runtime_error(std::string{"Unit not found "} + e.what()); } } @@ -93,13 +93,13 @@ public: return *this; } - template T value() const; static std::vector grib_selected_units; static std::vector complete_unit_order_; static std::vector list_supported_units() { std::vector result; + result.reserve(32); for (const auto& val : complete_unit_order_) { if (val == Value::MISSING) continue; From 91b5c19105cd21caf756897e6fbb5d967d6de90e Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Mon, 15 Jan 2024 11:36:21 +0000 Subject: [PATCH 118/125] Remove cerr --- src/grib_accessor_class_g2step_range.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 71fa118e4..3ed1366cf 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -234,7 +234,7 @@ static int pack_string(grib_accessor* a, const char* 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; - std::cerr << "VAL: " << val << std::endl; + //std::cerr << "VAL: " << val << std::endl; long force_step_units; if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) From fb8cd565ac7f51959c75e618c4351cb31651794e Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 15 Jan 2024 12:37:21 +0000 Subject: [PATCH 119/125] Set correct unit --- src/grib_accessor_class_g2step_range.cc | 39 ++++--------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/src/grib_accessor_class_g2step_range.cc b/src/grib_accessor_class_g2step_range.cc index 3ed1366cf..becc5da73 100644 --- a/src/grib_accessor_class_g2step_range.cc +++ b/src/grib_accessor_class_g2step_range.cc @@ -196,45 +196,16 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return GRIB_SUCCESS; } -//static int pack_string(grib_accessor* a, const char* val, size_t* len) -//{ -// grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a; -// grib_handle* h = grib_handle_of_accessor(a); - -// long start = 0, theEnd = -1; -// int ret = 0; -// char *p = NULL, *q = NULL; - -// start = strtol(val, &p, 10); -// theEnd = start; - -// if (*p != 0) -// theEnd = strtol(++p, &q, 10); -// ret = grib_set_long_internal(h, self->startStep, start); -// if (ret) -// return ret; - -// if (self->endStep != NULL) { -// ret = grib_set_long_internal(h, self->endStep, theEnd); -// if (ret) -// return ret; -// } - -// return 0; -//} - - // Step range format: [-] // and can be in different units -// stepRange="0" in instantaneous field is equivalent to set step=0 -// stepRange="0" in accumulated field is equivalent to ??? +// stepRange="X" in instantaneous field is equivalent to set step=X +// stepRange="X" in accumulated field is equivalent to startStep=X, endStep=startStep static int pack_string(grib_accessor* a, const char* 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; - //std::cerr << "VAL: " << val << std::endl; long force_step_units; if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS) @@ -268,12 +239,14 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len) return ret; if (self->end_step != NULL) { - if ((ret = grib_set_long_internal(h, "endStepUnit", step_1.unit().value()))) - return ret; if (steps.size() > 1) { + if ((ret = grib_set_long_internal(h, "endStepUnit", step_1.unit().value()))) + return ret; if ((ret = grib_set_long_internal(h, self->end_step, step_1.value()))) return ret; } else { + if ((ret = grib_set_long_internal(h, "endStepUnit", step_0.unit().value()))) + return ret; if ((ret = grib_set_long_internal(h, self->end_step, step_0.value()))) return ret; } From ccdd6f3d34fb8f74ae8fdf15f9173a864afc94fa Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 15 Jan 2024 14:58:27 +0000 Subject: [PATCH 120/125] Include stepUnits definition file --- definitions/grib2/stepUnits.def | 7 +++++++ definitions/grib2/template.4.20.def | 4 +--- definitions/grib2/template.4.forecast_time.def | 4 +--- definitions/grib2/template.4.forecast_time_44.def | 4 +--- definitions/grib2/template.4.localtime.def | 5 ++--- 5 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 definitions/grib2/stepUnits.def diff --git a/definitions/grib2/stepUnits.def b/definitions/grib2/stepUnits.def new file mode 100644 index 000000000..68efa462a --- /dev/null +++ b/definitions/grib2/stepUnits.def @@ -0,0 +1,7 @@ +# 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; + +meta stepUnits optimal_step_units(forecastTime,indicatorOfUnitOfTimeRange,lengthOfTimeRange,indicatorOfUnitForTimeRange) : transient,dump; +transient startStepUnit = 255 : hidden; # 255 means MISSING. See code table 4.4 +transient endStepUnit = 255 : hidden; diff --git a/definitions/grib2/template.4.20.def b/definitions/grib2/template.4.20.def index 83db46bc5..b739bf6bb 100644 --- a/definitions/grib2/template.4.20.def +++ b/definitions/grib2/template.4.20.def @@ -15,9 +15,7 @@ unsigned[1] numberOfRadarSitesUsed : dump; codetable[1] indicatorOfUnitOfTimeRange ('4.4.table',masterDir,localDir) : dump; alias indicatorOfUnitForForecastTime = indicatorOfUnitOfTimeRange; -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; +include "grib2/stepUnits.def" # Site latitude (in microdegrees) unsigned[4] siteLatitude : dump; diff --git a/definitions/grib2/template.4.forecast_time.def b/definitions/grib2/template.4.forecast_time.def index 8dc62f16b..f228d0a9e 100644 --- a/definitions/grib2/template.4.forecast_time.def +++ b/definitions/grib2/template.4.forecast_time.def @@ -12,9 +12,7 @@ alias minutesAfterReferenceTimeOfDataCutoff=minutesAfterDataCutoff; codetable[1] indicatorOfUnitOfTimeRange ('4.4.table',masterDir,localDir) : dump; alias indicatorOfUnitForForecastTime = indicatorOfUnitOfTimeRange; -meta stepUnits optimal_step_units(forecastTime,indicatorOfUnitOfTimeRange,lengthOfTimeRange,indicatorOfUnitForTimeRange) : transient,dump; -transient startStepUnit = 255 : hidden; # 255 means MISSING. See code table 4.4 -transient endStepUnit = 255 : hidden; +include "grib2/stepUnits.def"; # Forecast time in units defined by previous octet (GRIB-29: supports negative forecast time) signed[4] forecastTime : dump; diff --git a/definitions/grib2/template.4.forecast_time_44.def b/definitions/grib2/template.4.forecast_time_44.def index 0ad48c53b..aa35f543e 100644 --- a/definitions/grib2/template.4.forecast_time_44.def +++ b/definitions/grib2/template.4.forecast_time_44.def @@ -14,9 +14,7 @@ alias minutesAfterReferenceTimeOfDataCutoff=minutesAfterDataCutoff; codetable[1] indicatorOfUnitOfTimeRange ('4.4.table',masterDir,localDir) : dump; alias indicatorOfUnitForForecastTime = indicatorOfUnitOfTimeRange; -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; +include "grib2/stepUnits.def"; # Forecast time in units defined by previous octet # See GRIB-530: We have to make a special case for the error in WMO spec diff --git a/definitions/grib2/template.4.localtime.def b/definitions/grib2/template.4.localtime.def index 3432f8b6a..a3e47c754 100644 --- a/definitions/grib2/template.4.localtime.def +++ b/definitions/grib2/template.4.localtime.def @@ -3,9 +3,8 @@ remove is_localtime; transient is_localtime=1; -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; +#include "grib2/stepUnits.def"; + alias time.stepUnits = stepUnits; # Method used to calculate the field value at the local time specified in section 1 From 4c1048cb1e0c30b6fe089e2343890eaad3c24606 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Mon, 15 Jan 2024 15:07:59 +0000 Subject: [PATCH 121/125] Fix virtual function table (delimiters) --- src/grib_accessor_class_optimal_step_units.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 7ac95a902..940785e3e 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -17,9 +17,9 @@ START_CLASS_DEF CLASS = accessor SUPER = grib_accessor_class_gen - IMPLEMENTS = pack_long,unpack_long;dump - IMPLEMENTS = pack_string,unpack_string;dump - IMPLEMENTS = string_length + IMPLEMENTS = pack_long;unpack_long;dump + IMPLEMENTS = pack_string;unpack_string;dump + IMPLEMENTS = string_length;get_native_type IMPLEMENTS = init MEMBERS = const char* forecast_time_value MEMBERS = const char* forecast_time_unit From fb4aeedeb5c01ecf6bc228f6b3ad09c682d8d7a5 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 15 Jan 2024 15:18:35 +0000 Subject: [PATCH 122/125] Add pack_expression(), is_missing() and get_native_type() --- src/grib_accessor_class_optimal_step_units.cc | 52 +++++++++++++++++-- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index 7ac95a902..eee4303c1 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -17,9 +17,9 @@ START_CLASS_DEF CLASS = accessor SUPER = grib_accessor_class_gen - IMPLEMENTS = pack_long,unpack_long;dump - IMPLEMENTS = pack_string,unpack_string;dump - IMPLEMENTS = string_length + IMPLEMENTS = pack_long;unpack_long;dump + IMPLEMENTS = pack_string;unpack_string;dump + IMPLEMENTS = string_length;pack_expression;get_native_type;is_missing IMPLEMENTS = init MEMBERS = const char* forecast_time_value MEMBERS = const char* forecast_time_unit @@ -40,8 +40,10 @@ or edit "accessor.class" and rerun ./make_class.pl */ static int get_native_type(grib_accessor*); +static int is_missing(grib_accessor*); 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 pack_expression(grib_accessor*, grib_expression*); 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*); @@ -79,7 +81,7 @@ static grib_accessor_class _grib_accessor_class_optimal_step_units = { &get_native_type, /* get native type */ 0, /* get sub_section */ 0, /* pack_missing */ - 0, /* is_missing */ + &is_missing, /* is_missing */ &pack_long, /* pack_long */ &unpack_long, /* unpack_long */ 0, /* pack_double */ @@ -92,7 +94,7 @@ static grib_accessor_class _grib_accessor_class_optimal_step_units = { 0, /* unpack_string_array */ 0, /* pack_bytes */ 0, /* unpack_bytes */ - 0, /* pack_expression */ + &pack_expression, /* pack_expression */ 0, /* notify_change */ 0, /* update_size */ 0, /* preferred_size */ @@ -137,6 +139,39 @@ static size_t string_length(grib_accessor* a) return 255; } + +static int pack_expression(grib_accessor* a, grib_expression* e) +{ + const char* cval = NULL; + int ret = 0; + long lval = 0; + size_t len = 1; + grib_handle* hand = grib_handle_of_accessor(a); + + if (strcmp(e->cclass->name, "long") == 0) { + grib_expression_evaluate_long(hand, e, &lval); /* TDOD: check return value */ + //if (hand->context->debug) printf("ECCODES DEBUG grib_accessor_class_codetable::pack_expression %s %ld\n", a->name,lval); + ret = grib_pack_long(a, &lval, &len); + } + else { + char tmp[1024]; + len = sizeof(tmp); + cval = grib_expression_evaluate_string(hand, e, tmp, &len, &ret); + if (ret != GRIB_SUCCESS) { + grib_context_log(a->context, GRIB_LOG_ERROR, + "grib_accessor_codetable.%s: Unable to evaluate string %s to be set in %s", + __func__, grib_expression_get_name(e), a->name); + return ret; + } + len = strlen(cval) + 1; + //if (hand->context->debug) + // printf("ECCODES DEBUG grib_accessor_class_codetable::pack_expression %s %s\n", a->name, cval); + ret = grib_pack_string(a, cval, &len); + } + return ret; +} + + static long staticStepUnits = eccodes::Unit{eccodes::Unit::Value::MISSING}.value(); static long staticForceStepUnits = eccodes::Unit{eccodes::Unit::Value::MISSING}.value(); @@ -239,6 +274,13 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len) return GRIB_SUCCESS; } +// Step units are never missing +// If the user does not specify a step unit, we default to hours +static int is_missing(grib_accessor* a) +{ + return 0; +} + static int get_native_type(grib_accessor* a) { return GRIB_TYPE_LONG; From 0d6e197fb137ffef5af6af64900d6b09fa7ace46 Mon Sep 17 00:00:00 2001 From: Eugen Betke Date: Mon, 15 Jan 2024 15:59:17 +0000 Subject: [PATCH 123/125] Uncomment include step units --- definitions/grib2/template.4.localtime.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/definitions/grib2/template.4.localtime.def b/definitions/grib2/template.4.localtime.def index a3e47c754..3f082a227 100644 --- a/definitions/grib2/template.4.localtime.def +++ b/definitions/grib2/template.4.localtime.def @@ -3,7 +3,7 @@ remove is_localtime; transient is_localtime=1; -#include "grib2/stepUnits.def"; +include "grib2/stepUnits.def"; alias time.stepUnits = stepUnits; From 74048199a6c1ea0a9a2dd58f4b10cbe3dac27369 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Mon, 15 Jan 2024 16:24:11 +0000 Subject: [PATCH 124/125] Cleanup --- src/grib_accessor_class_codetable.cc | 2 +- src/grib_accessor_class_optimal_step_units.cc | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/grib_accessor_class_codetable.cc b/src/grib_accessor_class_codetable.cc index d450ffd97..18ee5d0ac 100644 --- a/src/grib_accessor_class_codetable.cc +++ b/src/grib_accessor_class_codetable.cc @@ -842,7 +842,7 @@ static int pack_expression(grib_accessor* a, grib_expression* e) grib_handle* hand = grib_handle_of_accessor(a); if (strcmp(e->cclass->name, "long") == 0) { - grib_expression_evaluate_long(hand, e, &lval); /* TDOD: check return value */ + grib_expression_evaluate_long(hand, e, &lval); /* TODO: check return value */ //if (hand->context->debug) printf("ECCODES DEBUG grib_accessor_class_codetable::pack_expression %s %ld\n", a->name,lval); ret = grib_pack_long(a, &lval, &len); } diff --git a/src/grib_accessor_class_optimal_step_units.cc b/src/grib_accessor_class_optimal_step_units.cc index eee4303c1..330531c24 100644 --- a/src/grib_accessor_class_optimal_step_units.cc +++ b/src/grib_accessor_class_optimal_step_units.cc @@ -139,7 +139,6 @@ static size_t string_length(grib_accessor* a) return 255; } - static int pack_expression(grib_accessor* a, grib_expression* e) { const char* cval = NULL; @@ -147,10 +146,10 @@ static int pack_expression(grib_accessor* a, grib_expression* e) long lval = 0; size_t len = 1; grib_handle* hand = grib_handle_of_accessor(a); + const char* cclass_name = a->cclass->name; if (strcmp(e->cclass->name, "long") == 0) { - grib_expression_evaluate_long(hand, e, &lval); /* TDOD: check return value */ - //if (hand->context->debug) printf("ECCODES DEBUG grib_accessor_class_codetable::pack_expression %s %ld\n", a->name,lval); + grib_expression_evaluate_long(hand, e, &lval); /* TODO: check return value */ ret = grib_pack_long(a, &lval, &len); } else { @@ -159,8 +158,8 @@ static int pack_expression(grib_accessor* a, grib_expression* e) cval = grib_expression_evaluate_string(hand, e, tmp, &len, &ret); if (ret != GRIB_SUCCESS) { grib_context_log(a->context, GRIB_LOG_ERROR, - "grib_accessor_codetable.%s: Unable to evaluate string %s to be set in %s", - __func__, grib_expression_get_name(e), a->name); + "%s.%s: Unable to evaluate string %s to be set in %s", + cclass_name, __func__, grib_expression_get_name(e), a->name); return ret; } len = strlen(cval) + 1; @@ -171,7 +170,6 @@ static int pack_expression(grib_accessor* a, grib_expression* e) return ret; } - static long staticStepUnits = eccodes::Unit{eccodes::Unit::Value::MISSING}.value(); static long staticForceStepUnits = eccodes::Unit{eccodes::Unit::Value::MISSING}.value(); From fa6cc1e32da44a3815e4b34c60c9d4f4bf7d87d9 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Mon, 15 Jan 2024 16:38:38 +0000 Subject: [PATCH 125/125] Remove useless 'stepunits' key (no longer in the mars namespace) --- definitions/grib1/section.1.def | 1 - definitions/grib2/products_s2s.def | 1 - definitions/grib2/template.4.localtime.def | 1 - definitions/grib2/template.4.point_in_time.def | 1 - definitions/grib2/template.4.statistical.def | 1 - tests/grib_sub_hourly.sh | 6 +++--- 6 files changed, 3 insertions(+), 8 deletions(-) diff --git a/definitions/grib1/section.1.def b/definitions/grib1/section.1.def index fcb306cb5..3d89bd277 100644 --- a/definitions/grib1/section.1.def +++ b/definitions/grib1/section.1.def @@ -222,7 +222,6 @@ alias ls.stepRange = stepRange; alias ls.dataDate = dataDate; alias mars.step = endStep; -alias stepunits = stepUnits; alias mars.date = dataDate; alias mars.levtype = indicatorOfTypeOfLevel; alias mars.time = dataTime; diff --git a/definitions/grib2/products_s2s.def b/definitions/grib2/products_s2s.def index 7063def51..13c90fb72 100644 --- a/definitions/grib2/products_s2s.def +++ b/definitions/grib2/products_s2s.def @@ -73,7 +73,6 @@ alias mars.type = marsType; # Normally MARS step is endStep but for monthly means we want stepRange if (stepType is "avg") { alias mars.step = stepRange; - alias stepunits = stepUnits; } if (isHindcast == 1) { diff --git a/definitions/grib2/template.4.localtime.def b/definitions/grib2/template.4.localtime.def index 3f082a227..5ae994b1d 100644 --- a/definitions/grib2/template.4.localtime.def +++ b/definitions/grib2/template.4.localtime.def @@ -81,7 +81,6 @@ if (numberOfForecastsUsedInLocalTime == 1) { alias mars.date = dateOfForecastUsedInLocalTime : dump; alias mars.time = timeOfForecastUsedInLocalTime : dump; alias mars.step = endStep; - alias stepunits = stepUnits; alias time.dataDate = dateOfForecastUsedInLocalTime; alias time.dataTime = timeOfForecastUsedInLocalTime; alias time.endStep = endStep; diff --git a/definitions/grib2/template.4.point_in_time.def b/definitions/grib2/template.4.point_in_time.def index 7e188b230..98885540a 100644 --- a/definitions/grib2/template.4.point_in_time.def +++ b/definitions/grib2/template.4.point_in_time.def @@ -7,7 +7,6 @@ alias step=startStep; alias marsStep=startStep; alias mars.step=startStep; -alias stepunits=stepUnits; alias marsStartStep = startStep; alias marsEndStep = endStep; diff --git a/definitions/grib2/template.4.statistical.def b/definitions/grib2/template.4.statistical.def index fa40bbd37..a2286e453 100644 --- a/definitions/grib2/template.4.statistical.def +++ b/definitions/grib2/template.4.statistical.def @@ -112,7 +112,6 @@ if (numberOfTimeRanges == 1 || numberOfTimeRanges == 2) { alias ls.stepRange=stepRange; alias mars.step=endStep; -alias stepunits=stepUnits; alias time.stepType=stepType; alias time.stepRange=stepRange; diff --git a/tests/grib_sub_hourly.sh b/tests/grib_sub_hourly.sh index 37799249e..19bdae580 100755 --- a/tests/grib_sub_hourly.sh +++ b/tests/grib_sub_hourly.sh @@ -70,7 +70,7 @@ keys_start_step="startStep,startStep:s,startStep:i,startStep:d,stepUnits:s" keys_end_step="endStep,endStep:s,endStep:i,endStep:d,stepUnits:s" ${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=h $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "0 h" -${tools_dir}/grib_set -s stepunits=m,step=59 $fn $temp +${tools_dir}/grib_set -s stepUnits=m,step=59 $fn $temp grib_check_key_equals $temp "-p $keys_step" "59m 59m 59 59 m" grib_check_key_equals $temp "-p $keys_step_range" "59m 59m 59 59 m" grib_check_key_equals $temp "-p $keys_start_step" "59m 59m 59 59 m" @@ -97,7 +97,7 @@ keys_s="step:s" keys_i="step:i,stepUnits:s" keys_d="step:d,stepUnits:s" -${tools_dir}/grib_set -s stepunits=m,step=60 $fn $temp +${tools_dir}/grib_set -s stepUnits=m,step=60 $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m" grib_check_key_equals $temp "-p $keys_s" "1$HOUR" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "60m" @@ -119,7 +119,7 @@ keys_s="step:s,startStep:s,endStep:s,stepRange:s,stepUnits:s" keys_i="step:i,startStep:i,endStep:i,stepRange:i,stepUnits:s" keys_d="step:d,startStep:d,endStep:d,stepRange:d,stepUnits:s" -${tools_dir}/grib_set -s stepunits=m,stepRange=60-120 $fn $temp +${tools_dir}/grib_set -s stepUnits=m,stepRange=60-120 $fn $temp grib_check_key_equals $temp "-p $low_level_keys" "60 m 60 m" grib_check_key_equals $temp "-p $keys_s" "2$HOUR 1$HOUR 2$HOUR 1$HOUR-2$HOUR h" grib_check_key_equals $temp "-p $keys_s -s stepUnits=m" "120m 60m 120m 60m-120m m"