mirror of https://github.com/ecmwf/eccodes.git
Merge branch 'develop' of github.com:ecmwf/eccodes into develop
This commit is contained in:
commit
0b45c664cb
|
@ -19,6 +19,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;
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -12,9 +12,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 (GRIB-29: supports negative forecast time)
|
||||
signed[4] forecastTime : dump;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -82,7 +81,6 @@ if (numberOfForecastsUsedInLocalTime == 1) {
|
|||
alias mars.date = dateOfForecastUsedInLocalTime : dump;
|
||||
alias mars.time = timeOfForecastUsedInLocalTime : dump;
|
||||
alias mars.step = endStep;
|
||||
|
||||
alias time.dataDate = dateOfForecastUsedInLocalTime;
|
||||
alias time.dataTime = timeOfForecastUsedInLocalTime;
|
||||
alias time.endStep = endStep;
|
||||
|
|
|
@ -9,7 +9,11 @@
|
|||
# nor does it submit to any jurisdiction.
|
||||
#
|
||||
list( APPEND eccodes_src_files
|
||||
step_unit.cc
|
||||
step.cc
|
||||
step_utilities.cc
|
||||
grib_api.h
|
||||
grib_timer.cc
|
||||
eccodes.h
|
||||
action.cc
|
||||
action_class_alias.cc
|
||||
|
@ -158,6 +162,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
|
||||
|
@ -253,7 +258,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
|
||||
|
|
|
@ -142,6 +142,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_packing_type;
|
||||
extern grib_accessor_class* grib_accessor_class_pad;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
*/
|
||||
|
||||
#include "grib_api_internal.h"
|
||||
#include "step.h"
|
||||
#include "step_utilities.h"
|
||||
#include <stdexcept>
|
||||
|
||||
/*
|
||||
This is used by make_class.pl
|
||||
|
||||
|
@ -16,9 +20,12 @@
|
|||
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
|
||||
MEMBERS = const char* unit
|
||||
IMPLEMENTS = get_native_type
|
||||
MEMBERS = const char* start_step_value
|
||||
MEMBERS = const char* step_units
|
||||
|
||||
MEMBERS = const char* year
|
||||
MEMBERS = const char* month
|
||||
|
@ -34,8 +41,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
|
||||
MEMBERS = const char* time_range_value
|
||||
MEMBERS = const char* typeOfTimeIncrement
|
||||
MEMBERS = const char* numberOfTimeRange
|
||||
|
||||
|
@ -53,8 +60,12 @@ 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_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*);
|
||||
|
||||
|
@ -64,8 +75,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;
|
||||
|
@ -78,8 +89,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;
|
||||
|
@ -101,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 */
|
||||
|
@ -109,10 +120,10 @@ 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 */
|
||||
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 */
|
||||
|
@ -145,8 +156,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++);
|
||||
|
@ -162,8 +173,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++);
|
||||
}
|
||||
|
@ -173,42 +184,6 @@ 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 bool is_special_expver(const grib_handle* h)
|
||||
{
|
||||
|
@ -229,66 +204,51 @@ static bool is_special_expver(const grib_handle* h)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int convert_time_range(
|
||||
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);
|
||||
|
||||
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;
|
||||
eccodes::Step time_range{*lengthOfTimeRange, indicatorOfUnitForTimeRange};
|
||||
time_range.set_unit(eccodes::Unit{stepUnits});
|
||||
if (time_range.value<long>() != time_range.value<double>()) {
|
||||
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<long>();
|
||||
}
|
||||
|
||||
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;
|
||||
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(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;
|
||||
|
||||
|
@ -301,31 +261,79 @@ static int unpack_one_time_range(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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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 */
|
||||
/* 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<double>(eccodes::Unit(step_units));
|
||||
}
|
||||
else {
|
||||
*val = start_step.value<double>(eccodes::Unit(start_step_unit));
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
@ -338,9 +346,9 @@ static int unpack_multiple_time_ranges(grib_accessor* a, long* val, size_t* len)
|
|||
/* 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 */
|
||||
|
@ -350,11 +358,71 @@ 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, 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;
|
||||
}
|
||||
}
|
||||
|
||||
grib_context_log(h->context, GRIB_LOG_ERROR,
|
||||
"Cannot calculate endStep. No time range specification with typeOfTimeIncrement = 2");
|
||||
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;
|
||||
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;
|
||||
|
||||
eccodes::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];
|
||||
|
||||
eccodes::Step time_range{the_coded_unit, the_coded_time_range};
|
||||
*val = (start_step + time_range).value<double>(eccodes::Unit(step_units));
|
||||
|
||||
return GRIB_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -370,38 +438,87 @@ 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;
|
||||
int err = 0;
|
||||
long start_step;
|
||||
grib_handle* h = grib_handle_of_accessor(a);
|
||||
int ret = 0;
|
||||
long start_step_value;
|
||||
long numberOfTimeRange;
|
||||
grib_handle* h = grib_handle_of_accessor(a);
|
||||
|
||||
if ((err = grib_get_long_internal(h, self->start_step, &start_step)))
|
||||
return err;
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
return unpack_one_time_range(a, val, len);
|
||||
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 {
|
||||
return unpack_multiple_time_ranges(a, val, len);
|
||||
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;
|
||||
}
|
||||
|
||||
static int pack_long(grib_accessor* a, const 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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
int err = 0;
|
||||
|
||||
long year;
|
||||
|
@ -411,28 +528,30 @@ 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 start_step_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 coded_time_range, time_range, typeOfTimeIncrement;
|
||||
long typeOfTimeIncrement;
|
||||
|
||||
double dend, dstep;
|
||||
int show_hours = a->context->show_hour_stepunit;
|
||||
|
||||
eccodes::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, *val);
|
||||
err = grib_set_long_internal(h, "startStepUnit", end_step.unit().value<long>());
|
||||
err = grib_set_long_internal(h, self->start_step_value, end_step.value<long>());
|
||||
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)))
|
||||
if ((err = grib_get_long_internal(h, self->time_range_unit, &time_range_unit)))
|
||||
return err;
|
||||
if ((err = grib_get_long_internal(h, self->year, &year)))
|
||||
return err;
|
||||
|
@ -447,16 +566,30 @@ 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, "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 (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;
|
||||
}
|
||||
|
||||
if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement)))
|
||||
return err;
|
||||
|
||||
time_range = *val - start_step;
|
||||
eccodes::Step start_step{start_step_value, start_step_unit};
|
||||
eccodes::Step time_range = end_step - start_step;
|
||||
|
||||
if (time_range < 0) {
|
||||
if (time_range.value<double>() < 0) {
|
||||
grib_context_log(h->context, GRIB_LOG_ERROR,
|
||||
"endStep < startStep (%ld < %ld)", *val, start_step);
|
||||
"endStep < startStep (%s < %s)", end_step.value<std::string>("%g", show_hours).c_str(), start_step.value<std::string>("%g", show_hours).c_str());
|
||||
return GRIB_WRONG_STEP;
|
||||
}
|
||||
|
||||
|
@ -464,7 +597,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 = end_step.value<double>(eccodes::Unit{eccodes::Unit::Value::DAY});
|
||||
dend += dstep;
|
||||
|
||||
err = grib_julian_to_datetime(dend, &year_of_end_of_interval, &month_of_end_of_interval,
|
||||
|
@ -486,21 +619,130 @@ 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)))
|
||||
return err;
|
||||
coded_time_range = time_range;
|
||||
const char* forecast_time_value_key = "forecastTime";
|
||||
const char* forecast_time_unit_key = "indicatorOfUnitOfTimeRange";
|
||||
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 = eccodes::Step{start_step.value<long>(eccodes::Unit{force_step_units}), eccodes::Unit{force_step_units}};
|
||||
time_range_opt = eccodes::Step{time_range.value<long>(eccodes::Unit{force_step_units}), eccodes::Unit{force_step_units}};
|
||||
}
|
||||
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 ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_value, time_range_opt.value<long>())) != GRIB_SUCCESS)
|
||||
return err;
|
||||
if ((err = grib_set_long_internal(grib_handle_of_accessor(a), self->time_range_unit, time_range_opt.unit().value<long>())) != GRIB_SUCCESS)
|
||||
return err;
|
||||
if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_value_key, forecast_time_opt.value<long>())) != GRIB_SUCCESS)
|
||||
return err;
|
||||
if ((err = grib_set_long_internal(grib_handle_of_accessor(a), forecast_time_unit_key, forecast_time_opt.unit().value<long>())) != GRIB_SUCCESS)
|
||||
return err;
|
||||
|
||||
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;
|
||||
grib_handle* h = grib_handle_of_accessor(a);
|
||||
int ret = 0;
|
||||
char fp_format[128] = "%g";
|
||||
size_t fp_format_len = sizeof(fp_format);
|
||||
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;
|
||||
if ((ret = grib_get_long_internal(h, self->step_units, &step_units)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
if ((ret = grib_get_string(h, "formatForDoubles", fp_format, &fp_format_len)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
|
||||
try {
|
||||
eccodes::Step step(step_value, step_units);
|
||||
step.set_unit(step_units);
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
ss << step.value<std::string>(fp_format, show_hours);
|
||||
|
||||
size_t 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(h->context, GRIB_LOG_ERROR, "grib_accessor_g2end_step::unpack_string: %s", e.what());
|
||||
return GRIB_DECODING_ERROR;
|
||||
}
|
||||
|
||||
return GRIB_SUCCESS;
|
||||
}
|
||||
|
||||
static int pack_long(grib_accessor* a, const long* val, size_t* len)
|
||||
{
|
||||
grib_handle* h = grib_handle_of_accessor(a);
|
||||
int ret;
|
||||
|
||||
long force_step_units;
|
||||
if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
|
||||
try {
|
||||
long end_step_unit;
|
||||
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 (eccodes::Unit{end_step_unit} == eccodes::Unit{eccodes::Unit::Value::MISSING})
|
||||
end_step_unit = eccodes::Unit{eccodes::Unit::Value::HOUR}.value<long>();
|
||||
}
|
||||
else {
|
||||
end_step_unit = force_step_units;
|
||||
}
|
||||
ret = pack_long_(a, *val, end_step_unit);
|
||||
}
|
||||
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 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;
|
||||
long force_step_units;
|
||||
if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
|
||||
try {
|
||||
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<long>())) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
|
||||
if ((ret = pack_long_(a, end_step.value<long>(), end_step.unit().value<long>())) != 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;
|
||||
}
|
||||
|
||||
static int get_native_type(grib_accessor* a)
|
||||
{
|
||||
return GRIB_TYPE_STRING;
|
||||
}
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
* 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"
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
/*
|
||||
This is used by make_class.pl
|
||||
|
||||
|
@ -20,11 +21,13 @@
|
|||
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
|
||||
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
|
||||
|
||||
*/
|
||||
|
@ -42,11 +45,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_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
|
||||
|
@ -54,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;
|
||||
|
@ -69,7 +72,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 */
|
||||
|
@ -83,7 +86,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 */
|
||||
|
@ -119,83 +122,141 @@ 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 = 0, theEnd = 0;
|
||||
double start_step_value = 0;
|
||||
double end_step_value = 0;
|
||||
long step_units;
|
||||
|
||||
ret = grib_get_long_internal(h, self->startStep, &start);
|
||||
if (ret)
|
||||
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)
|
||||
return ret;
|
||||
try {
|
||||
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;
|
||||
}
|
||||
|
||||
if (self->endStep == NULL) {
|
||||
snprintf(buf, sizeof(buf), "%ld", start);
|
||||
}
|
||||
else {
|
||||
ret = grib_get_long_internal(h, self->endStep, &theEnd);
|
||||
if (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;
|
||||
|
||||
if (start == theEnd) {
|
||||
snprintf(buf, sizeof(buf), "%ld", theEnd);
|
||||
eccodes::Step start_step{start_step_value, step_units};
|
||||
if (self->end_step == NULL) {
|
||||
ss << start_step.value<std::string>(fp_format, show_hours);
|
||||
}
|
||||
else {
|
||||
snprintf(buf, sizeof(buf), "%ld-%ld", start, theEnd);
|
||||
if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
|
||||
eccodes::Step end_step{end_step_value, step_units};
|
||||
|
||||
if (start_step_value == end_step_value) {
|
||||
ss << end_step.value<std::string>(fp_format, show_hours);
|
||||
}
|
||||
else {
|
||||
ss << start_step.value<std::string>(fp_format, show_hours) << "-" << end_step.value<std::string>(fp_format, show_hours);
|
||||
}
|
||||
}
|
||||
|
||||
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 = strlen(buf) + 1;
|
||||
|
||||
if (*len < size)
|
||||
return GRIB_ARRAY_TOO_SMALL;
|
||||
|
||||
*len = size;
|
||||
|
||||
memcpy(val, buf, size);
|
||||
|
||||
return GRIB_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// Step range format: <start_step>[-<end_step>]
|
||||
// <start_step> and <end_step> can be in different units
|
||||
// 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);
|
||||
|
||||
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)
|
||||
long force_step_units;
|
||||
if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
|
||||
if (self->endStep != NULL) {
|
||||
ret = grib_set_long_internal(h, self->endStep, theEnd);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
try {
|
||||
std::vector<eccodes::Step> 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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
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 = eccodes::Step{steps[0].value<long>(eccodes::Unit{force_step_units}), eccodes::Unit{force_step_units}};
|
||||
if (steps.size() > 1) {
|
||||
step_1 = eccodes::Step{steps[1].value<long>(eccodes::Unit{force_step_units}), eccodes::Unit{force_step_units}};
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = grib_set_long_internal(h, "startStepUnit", step_0.unit().value<long>())))
|
||||
return ret;
|
||||
if ((ret = set_step(h, "forecastTime" , "indicatorOfUnitOfTimeRange", step_0)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
|
||||
if (self->end_step != NULL) {
|
||||
if (steps.size() > 1) {
|
||||
if ((ret = grib_set_long_internal(h, "endStepUnit", step_1.unit().value<long>())))
|
||||
return ret;
|
||||
if ((ret = grib_set_long_internal(h, self->end_step, step_1.value<long>())))
|
||||
return ret;
|
||||
} else {
|
||||
if ((ret = grib_set_long_internal(h, "endStepUnit", step_0.unit().value<long>())))
|
||||
return ret;
|
||||
if ((ret = grib_set_long_internal(h, self->end_step, step_0.value<long>())))
|
||||
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;
|
||||
}
|
||||
return GRIB_SUCCESS;
|
||||
}
|
||||
|
||||
static int value_count(grib_accessor* a, long* count)
|
||||
|
@ -218,29 +279,86 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len)
|
|||
return pack_string(a, buff, &bufflen);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
long end_start_value = 0;
|
||||
long end_step_value = 0;
|
||||
long step_units = 0;
|
||||
|
||||
if ((ret = grib_get_long_internal(h, self->start_step, &end_start_value)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
try {
|
||||
if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS)
|
||||
throw std::runtime_error("Failed to get stepUnits");
|
||||
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;
|
||||
}
|
||||
|
||||
if ((err = unpack_string(a, buff, &bufflen)) != GRIB_SUCCESS)
|
||||
return err;
|
||||
eccodes::Step start_step{end_start_value, step_units};
|
||||
if (self->end_step == NULL) {
|
||||
*val = start_step.value<long>();
|
||||
}
|
||||
else {
|
||||
if ((ret = grib_get_long_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
eccodes::Step end_step{end_step_value, step_units};
|
||||
*val = end_step.value<long>();
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
grib_context_log(a->context, GRIB_LOG_ERROR, "Failed to unpack step range: %s", e.what());
|
||||
return GRIB_DECODING_ERROR;
|
||||
}
|
||||
|
||||
start = strtol(buff, &p, 10);
|
||||
theEnd = start;
|
||||
if (*p != 0)
|
||||
theEnd = strtol(++p, &q, 10);
|
||||
|
||||
*val = theEnd;
|
||||
|
||||
return 0;
|
||||
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");
|
||||
|
||||
try {
|
||||
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;
|
||||
}
|
||||
|
||||
eccodes::Step start_step{end_start_value, step_units};
|
||||
if (self->end_step == NULL) {
|
||||
*val = start_step.value<long>();
|
||||
}
|
||||
else {
|
||||
if ((ret = grib_get_double_internal(h, self->end_step, &end_step_value)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
eccodes::Step end_step{end_step_value, step_units};
|
||||
*val = end_step.value<double>();
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static int get_native_type(grib_accessor* a)
|
||||
{
|
||||
return GRIB_TYPE_STRING;
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* (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 "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 = string_length;pack_expression;get_native_type;is_missing
|
||||
IMPLEMENTS = init
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
/* 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 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*);
|
||||
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* 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;
|
||||
|
||||
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 */
|
||||
&is_missing, /* 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 */
|
||||
&pack_expression, /* 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->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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
const char* cclass_name = a->cclass->name;
|
||||
|
||||
if (strcmp(e->cclass->name, "long") == 0) {
|
||||
grib_expression_evaluate_long(hand, e, &lval); /* TODO: check return value */
|
||||
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,
|
||||
"%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;
|
||||
//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<long>();
|
||||
static long staticForceStepUnits = eccodes::Unit{eccodes::Unit::Value::MISSING}.value<long>();
|
||||
|
||||
static int pack_long(grib_accessor* a, const long* val, size_t* len)
|
||||
{
|
||||
grib_handle* h = grib_handle_of_accessor(a);
|
||||
auto supported_units = eccodes::Unit::list_supported_units();
|
||||
try {
|
||||
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{"eccodes::Unit not supported"};
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
std::string supported_units_str;
|
||||
for (auto& u : supported_units)
|
||||
supported_units_str += eccodes::Unit{u}.value<std::string>() + ",";
|
||||
supported_units_str.pop_back();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int ret;
|
||||
staticStepUnits = *val;
|
||||
if ((ret = grib_set_long_internal(h, "forceStepUnits", *val)) != GRIB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return GRIB_SUCCESS;
|
||||
}
|
||||
|
||||
static int unpack_long(grib_accessor* a, long* val, size_t* len)
|
||||
{
|
||||
try {
|
||||
if (eccodes::Unit{staticStepUnits} != eccodes::Unit{eccodes::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);
|
||||
|
||||
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<long>();
|
||||
}
|
||||
else if (forecast_time_opt && !time_range_opt) {
|
||||
*val = forecast_time_opt.value().optimize_unit().unit().value<long>();
|
||||
}
|
||||
else if (!forecast_time_opt && time_range_opt) {
|
||||
*val = time_range_opt.value().optimize_unit().unit().value<long>();
|
||||
}
|
||||
else if (!forecast_time_opt && !time_range_opt) {
|
||||
*val = eccodes::Unit{eccodes::Unit::Value::HOUR}.value<long>();
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
grib_context_log(a->context, GRIB_LOG_ERROR, e.what());
|
||||
return GRIB_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return GRIB_SUCCESS;
|
||||
}
|
||||
|
||||
static int pack_string(grib_accessor* a, const char* val, size_t* len)
|
||||
{
|
||||
try {
|
||||
long unit = eccodes::Unit{val}.value<long>();
|
||||
pack_long(a, &unit, len);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
auto supported_units = eccodes::Unit::list_supported_units();
|
||||
std::string supported_units_str;
|
||||
for (auto& u : supported_units)
|
||||
supported_units_str += eccodes::Unit{u}.value<std::string>() + ",";
|
||||
supported_units_str.pop_back();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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", eccodes::Unit{unit}.value<std::string>().c_str());
|
||||
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;
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
#include "grib_api_internal.h"
|
||||
#include "step.h"
|
||||
|
||||
/*
|
||||
This is used by make_class.pl
|
||||
|
@ -127,10 +128,10 @@ 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_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;
|
||||
|
||||
hour = step/3600;
|
||||
minute = step/60 % 60;
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
*/
|
||||
|
||||
#include "grib_api_internal.h"
|
||||
#include "step.h"
|
||||
#include "step_utilities.h"
|
||||
#include <stdexcept>
|
||||
/*
|
||||
This is used by make_class.pl
|
||||
|
||||
|
@ -16,12 +19,15 @@
|
|||
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* codedStep
|
||||
MEMBERS = const char* codedUnits
|
||||
MEMBERS = const char* stepUnits
|
||||
MEMBERS = const char* indicatorOfUnitForTimeRange
|
||||
MEMBERS = const char* lengthOfTimeRange
|
||||
IMPLEMENTS = get_native_type
|
||||
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
|
||||
|
||||
|
@ -37,8 +43,12 @@ 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_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*);
|
||||
|
||||
|
@ -48,11 +58,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;
|
||||
|
@ -72,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 */
|
||||
|
@ -80,10 +90,10 @@ 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 */
|
||||
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 */
|
||||
|
@ -113,13 +123,13 @@ 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->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)
|
||||
|
@ -127,139 +137,217 @@ 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: 'stepUnits' 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)
|
||||
{
|
||||
grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a;
|
||||
int err = 0;
|
||||
long codedStep, codedUnits, stepUnits;
|
||||
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, self->codedUnits, &codedUnits)))
|
||||
if ((err= grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS)
|
||||
return err;
|
||||
if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits)))
|
||||
if ((err = grib_get_long_internal(h, self->forecast_time_unit, &forecast_time_unit)))
|
||||
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 (*val < 0) {
|
||||
factor = 60;
|
||||
if (u2s2[codedUnits] % factor)
|
||||
return GRIB_DECODING_ERROR;
|
||||
if (u2s[stepUnits] % factor)
|
||||
return GRIB_DECODING_ERROR;
|
||||
u2sf = u2s2[codedUnits] / factor;
|
||||
*val = codedStep * u2sf;
|
||||
u2sf_step_unit = u2s[stepUnits] / factor;
|
||||
}
|
||||
else {
|
||||
u2sf_step_unit = u2s[stepUnits];
|
||||
}
|
||||
try {
|
||||
eccodes::Step step{forecast_time_value, forecast_time_unit};
|
||||
step.optimize_unit();
|
||||
|
||||
if (*val % u2sf_step_unit != 0) {
|
||||
err = grib_set_long_internal(h, self->stepUnits, codedUnits);
|
||||
*val = codedStep;
|
||||
if ((err = grib_set_long_internal(h, "startStepUnit", eccodes::Unit{step_units}.value<long>())) != GRIB_SUCCESS)
|
||||
return err;
|
||||
}
|
||||
*val = *val / u2sf_step_unit;
|
||||
|
||||
*val = step.value<long>(eccodes::Unit{step_units});
|
||||
}
|
||||
else
|
||||
*val = codedStep;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
try {
|
||||
eccodes::Step step{forecast_time_value, forecast_time_unit};
|
||||
|
||||
if ((err = grib_set_long_internal(h, "startStepUnit", eccodes::Unit{step_units}.value<long>())) != GRIB_SUCCESS)
|
||||
return err;
|
||||
|
||||
*val = step.value<double>(eccodes::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;
|
||||
}
|
||||
|
||||
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);
|
||||
int err = 0;
|
||||
long forecast_time_unit;
|
||||
long start_step_value_old;
|
||||
long start_step_unit_old;
|
||||
size_t len = 0;
|
||||
|
||||
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, "startStepUnit", &start_step_unit_old)) != GRIB_SUCCESS)
|
||||
return err;
|
||||
|
||||
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);
|
||||
|
||||
if (time_range_opt) {
|
||||
auto time_range = time_range_opt.value();
|
||||
time_range = time_range - (forecast_time - start_step_old);
|
||||
if (time_range.value<long>() < 0)
|
||||
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;
|
||||
if ((err = grib_set_long_internal(h, "startStepUnit", forecast_time.unit().value<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;
|
||||
}
|
||||
|
||||
if (eccodes::Unit{force_step_units} == eccodes::Unit{eccodes::Unit::Value::MISSING}) {
|
||||
forecast_time.optimize_unit();
|
||||
}
|
||||
|
||||
if ((err = grib_set_long_internal(h, "startStepUnit", forecast_time.unit().value<long>())) != GRIB_SUCCESS)
|
||||
return err;
|
||||
if ((err = set_step(h, self->forecast_time_value, self->forecast_time_unit, forecast_time)) != GRIB_SUCCESS)
|
||||
return err;
|
||||
|
||||
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;
|
||||
long indicatorOfUnitForTimeRange, lengthOfTimeRange;
|
||||
grib_handle* h = grib_handle_of_accessor(a);
|
||||
int ret = GRIB_SUCCESS;
|
||||
|
||||
if ((err = grib_get_long_internal(h, self->codedUnits, &codedUnits)))
|
||||
return err;
|
||||
if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits)))
|
||||
return err;
|
||||
long force_step_units;
|
||||
if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
|
||||
unpack_long(a, &oldStep, len);
|
||||
long start_step_unit;
|
||||
try {
|
||||
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 (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;
|
||||
if (eccodes::Unit{start_step_unit} == eccodes::Unit{eccodes::Unit::Value::MISSING})
|
||||
start_step_unit = eccodes::Unit{eccodes::Unit::Value::HOUR}.value<long>();
|
||||
}
|
||||
else {
|
||||
codedStep = codedStep / u2s2[codedUnits];
|
||||
start_step_unit = force_step_units;
|
||||
}
|
||||
}
|
||||
else {
|
||||
codedStep = *val;
|
||||
catch (std::exception& e) {
|
||||
grib_context_log(h->context, GRIB_LOG_ERROR, "step_in_units: %s", e.what());
|
||||
return GRIB_DECODING_ERROR;
|
||||
}
|
||||
|
||||
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 = pack_long_new_(a, *val, start_step_unit, force_step_units);
|
||||
|
||||
return grib_set_long_internal(grib_handle_of_accessor(a), self->codedStep, codedStep);
|
||||
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 = eccodes::Unit(eccodes::Unit::Value::MISSING).value<long>();
|
||||
int ret = GRIB_SUCCESS;
|
||||
long force_step_units;
|
||||
if ((ret = grib_get_long_internal(h, "forceStepUnits", &force_step_units)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
|
||||
try {
|
||||
eccodes::Step step = step_from_string(val, eccodes::Unit{force_step_units});
|
||||
if ((ret = pack_long_new_(a, step.value<long>(), step.unit().value<long>(), force_step_units)) != 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;
|
||||
}
|
||||
|
||||
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 = GRIB_SUCCESS;
|
||||
long start_step_value;
|
||||
long start_step_unit;
|
||||
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;
|
||||
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, "formatForDoubles", fp_format, &fp_format_len)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
|
||||
try {
|
||||
eccodes::Step step{start_step_value, start_step_unit};
|
||||
std::stringstream ss;
|
||||
|
||||
ss << step.value<std::string>(fp_format, show_hours);
|
||||
|
||||
size_t 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(h->context, GRIB_LOG_ERROR, "step_in_units: %s", e.what());
|
||||
return GRIB_DECODING_ERROR;
|
||||
}
|
||||
|
||||
return GRIB_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int get_native_type(grib_accessor* a)
|
||||
{
|
||||
return GRIB_TYPE_STRING;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#line 6 "accessor_class_list.gperf"
|
||||
struct accessor_class_hash { char *name; grib_accessor_class **cclass;};
|
||||
|
||||
#define TOTAL_KEYWORDS 203
|
||||
#define TOTAL_KEYWORDS 204
|
||||
#define MIN_WORD_LENGTH 1
|
||||
#define MAX_WORD_LENGTH 44
|
||||
#define MIN_HASH_VALUE 1
|
||||
|
@ -117,21 +117,21 @@ static const struct accessor_class_hash classes[] =
|
|||
#line 9 "accessor_class_list.gperf"
|
||||
{" "},
|
||||
{""}, {""}, {""}, {""},
|
||||
#line 177 "accessor_class_list.gperf"
|
||||
#line 178 "accessor_class_list.gperf"
|
||||
{"size", &grib_accessor_class_size},
|
||||
#line 12 "accessor_class_list.gperf"
|
||||
{"ascii", &grib_accessor_class_ascii},
|
||||
#line 174 "accessor_class_list.gperf"
|
||||
#line 175 "accessor_class_list.gperf"
|
||||
{"signed", &grib_accessor_class_signed},
|
||||
#line 154 "accessor_class_list.gperf"
|
||||
#line 155 "accessor_class_list.gperf"
|
||||
{"pad", &grib_accessor_class_pad},
|
||||
#line 180 "accessor_class_list.gperf"
|
||||
#line 181 "accessor_class_list.gperf"
|
||||
{"spd", &grib_accessor_class_spd},
|
||||
{""},
|
||||
#line 75 "accessor_class_list.gperf"
|
||||
{"dirty", &grib_accessor_class_dirty},
|
||||
{""},
|
||||
#line 175 "accessor_class_list.gperf"
|
||||
#line 176 "accessor_class_list.gperf"
|
||||
{"signed_bits", &grib_accessor_class_signed_bits},
|
||||
{""},
|
||||
#line 66 "accessor_class_list.gperf"
|
||||
|
@ -141,7 +141,7 @@ static const struct accessor_class_hash classes[] =
|
|||
{"data_simple_packing", &grib_accessor_class_data_simple_packing},
|
||||
#line 68 "accessor_class_list.gperf"
|
||||
{"data_secondary_bitmap", &grib_accessor_class_data_secondary_bitmap},
|
||||
#line 168 "accessor_class_list.gperf"
|
||||
#line 169 "accessor_class_list.gperf"
|
||||
{"section", &grib_accessor_class_section},
|
||||
#line 43 "accessor_class_list.gperf"
|
||||
{"data_apply_bitmap", &grib_accessor_class_data_apply_bitmap},
|
||||
|
@ -155,36 +155,36 @@ static const struct accessor_class_hash classes[] =
|
|||
{"data_jpeg2000_packing", &grib_accessor_class_data_jpeg2000_packing},
|
||||
#line 65 "accessor_class_list.gperf"
|
||||
{"data_png_packing", &grib_accessor_class_data_png_packing},
|
||||
#line 170 "accessor_class_list.gperf"
|
||||
{"section_padding", &grib_accessor_class_section_padding},
|
||||
#line 171 "accessor_class_list.gperf"
|
||||
{"section_padding", &grib_accessor_class_section_padding},
|
||||
#line 172 "accessor_class_list.gperf"
|
||||
{"section_pointer", &grib_accessor_class_section_pointer},
|
||||
#line 44 "accessor_class_list.gperf"
|
||||
{"data_apply_boustrophedonic", &grib_accessor_class_data_apply_boustrophedonic},
|
||||
{""}, {""}, {""}, {""},
|
||||
#line 80 "accessor_class_list.gperf"
|
||||
{"expanded_descriptors", &grib_accessor_class_expanded_descriptors},
|
||||
#line 155 "accessor_class_list.gperf"
|
||||
#line 156 "accessor_class_list.gperf"
|
||||
{"padding", &grib_accessor_class_padding},
|
||||
#line 45 "accessor_class_list.gperf"
|
||||
{"data_apply_boustrophedonic_bitmap", &grib_accessor_class_data_apply_boustrophedonic_bitmap},
|
||||
#line 110 "accessor_class_list.gperf"
|
||||
{"gds_is_present", &grib_accessor_class_gds_is_present},
|
||||
#line 167 "accessor_class_list.gperf"
|
||||
#line 168 "accessor_class_list.gperf"
|
||||
{"second_order_bits_per_value", &grib_accessor_class_second_order_bits_per_value},
|
||||
#line 169 "accessor_class_list.gperf"
|
||||
#line 170 "accessor_class_list.gperf"
|
||||
{"section_length", &grib_accessor_class_section_length},
|
||||
#line 113 "accessor_class_list.gperf"
|
||||
{"getenv", &grib_accessor_class_getenv},
|
||||
#line 57 "accessor_class_list.gperf"
|
||||
{"data_g22order_packing", &grib_accessor_class_data_g22order_packing},
|
||||
#line 189 "accessor_class_list.gperf"
|
||||
#line 190 "accessor_class_list.gperf"
|
||||
{"time", &grib_accessor_class_time},
|
||||
{""},
|
||||
#line 61 "accessor_class_list.gperf"
|
||||
{"data_g2shsimple_packing", &grib_accessor_class_data_g2shsimple_packing},
|
||||
{""},
|
||||
#line 153 "accessor_class_list.gperf"
|
||||
#line 154 "accessor_class_list.gperf"
|
||||
{"packing_type", &grib_accessor_class_packing_type},
|
||||
#line 62 "accessor_class_list.gperf"
|
||||
{"data_g2simple_packing", &grib_accessor_class_data_g2simple_packing},
|
||||
|
@ -201,25 +201,25 @@ static const struct accessor_class_hash classes[] =
|
|||
#line 141 "accessor_class_list.gperf"
|
||||
{"nearest", &grib_accessor_class_nearest},
|
||||
{""},
|
||||
#line 156 "accessor_class_list.gperf"
|
||||
#line 157 "accessor_class_list.gperf"
|
||||
{"padto", &grib_accessor_class_padto},
|
||||
#line 187 "accessor_class_list.gperf"
|
||||
#line 188 "accessor_class_list.gperf"
|
||||
{"sum", &grib_accessor_class_sum},
|
||||
{""},
|
||||
#line 107 "accessor_class_list.gperf"
|
||||
{"g2lon", &grib_accessor_class_g2lon},
|
||||
#line 201 "accessor_class_list.gperf"
|
||||
#line 202 "accessor_class_list.gperf"
|
||||
{"uint8", &grib_accessor_class_uint8},
|
||||
{""},
|
||||
#line 186 "accessor_class_list.gperf"
|
||||
#line 187 "accessor_class_list.gperf"
|
||||
{"step_in_units", &grib_accessor_class_step_in_units},
|
||||
#line 63 "accessor_class_list.gperf"
|
||||
{"data_g2simple_packing_with_preprocessing", &grib_accessor_class_data_g2simple_packing_with_preprocessing},
|
||||
#line 199 "accessor_class_list.gperf"
|
||||
#line 200 "accessor_class_list.gperf"
|
||||
{"uint64", &grib_accessor_class_uint64},
|
||||
#line 47 "accessor_class_list.gperf"
|
||||
{"data_complex_packing", &grib_accessor_class_data_complex_packing},
|
||||
#line 197 "accessor_class_list.gperf"
|
||||
#line 198 "accessor_class_list.gperf"
|
||||
{"uint32", &grib_accessor_class_uint32},
|
||||
#line 13 "accessor_class_list.gperf"
|
||||
{"bit", &grib_accessor_class_bit},
|
||||
|
@ -245,10 +245,10 @@ static const struct accessor_class_hash classes[] =
|
|||
#line 16 "accessor_class_list.gperf"
|
||||
{"bits_per_value", &grib_accessor_class_bits_per_value},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
#line 165 "accessor_class_list.gperf"
|
||||
#line 166 "accessor_class_list.gperf"
|
||||
{"scale", &grib_accessor_class_scale},
|
||||
{""},
|
||||
#line 183 "accessor_class_list.gperf"
|
||||
#line 184 "accessor_class_list.gperf"
|
||||
{"statistics", &grib_accessor_class_statistics},
|
||||
#line 102 "accessor_class_list.gperf"
|
||||
{"g2date", &grib_accessor_class_g2date},
|
||||
|
@ -265,13 +265,13 @@ static const struct accessor_class_hash classes[] =
|
|||
{"gds_not_present_bitmap", &grib_accessor_class_gds_not_present_bitmap},
|
||||
#line 122 "accessor_class_list.gperf"
|
||||
{"iterator", &grib_accessor_class_iterator},
|
||||
#line 184 "accessor_class_list.gperf"
|
||||
#line 185 "accessor_class_list.gperf"
|
||||
{"statistics_spectral", &grib_accessor_class_statistics_spectral},
|
||||
#line 46 "accessor_class_list.gperf"
|
||||
{"data_ccsds_packing", &grib_accessor_class_data_ccsds_packing},
|
||||
#line 145 "accessor_class_list.gperf"
|
||||
{"number_of_points_gaussian", &grib_accessor_class_number_of_points_gaussian},
|
||||
#line 204 "accessor_class_list.gperf"
|
||||
#line 205 "accessor_class_list.gperf"
|
||||
{"unsigned", &grib_accessor_class_unsigned},
|
||||
#line 138 "accessor_class_list.gperf"
|
||||
{"md5", &grib_accessor_class_md5},
|
||||
|
@ -280,30 +280,30 @@ static const struct accessor_class_hash classes[] =
|
|||
{"g2_aerosol", &grib_accessor_class_g2_aerosol},
|
||||
#line 139 "accessor_class_list.gperf"
|
||||
{"message", &grib_accessor_class_message},
|
||||
#line 205 "accessor_class_list.gperf"
|
||||
#line 206 "accessor_class_list.gperf"
|
||||
{"unsigned_bits", &grib_accessor_class_unsigned_bits},
|
||||
#line 172 "accessor_class_list.gperf"
|
||||
#line 173 "accessor_class_list.gperf"
|
||||
{"select_step_template", &grib_accessor_class_select_step_template},
|
||||
#line 136 "accessor_class_list.gperf"
|
||||
{"mars_param", &grib_accessor_class_mars_param},
|
||||
#line 202 "accessor_class_list.gperf"
|
||||
#line 203 "accessor_class_list.gperf"
|
||||
{"unexpanded_descriptors", &grib_accessor_class_unexpanded_descriptors},
|
||||
#line 191 "accessor_class_list.gperf"
|
||||
#line 192 "accessor_class_list.gperf"
|
||||
{"to_integer", &grib_accessor_class_to_integer},
|
||||
{""}, {""}, {""},
|
||||
#line 176 "accessor_class_list.gperf"
|
||||
#line 177 "accessor_class_list.gperf"
|
||||
{"simple_packing_error", &grib_accessor_class_simple_packing_error},
|
||||
#line 185 "accessor_class_list.gperf"
|
||||
#line 186 "accessor_class_list.gperf"
|
||||
{"step_human_readable", &grib_accessor_class_step_human_readable},
|
||||
#line 140 "accessor_class_list.gperf"
|
||||
{"message_copy", &grib_accessor_class_message_copy},
|
||||
#line 161 "accessor_class_list.gperf"
|
||||
#line 162 "accessor_class_list.gperf"
|
||||
{"raw", &grib_accessor_class_raw},
|
||||
{""}, {""},
|
||||
#line 200 "accessor_class_list.gperf"
|
||||
#line 201 "accessor_class_list.gperf"
|
||||
{"uint64_little_endian", &grib_accessor_class_uint64_little_endian},
|
||||
{""},
|
||||
#line 198 "accessor_class_list.gperf"
|
||||
#line 199 "accessor_class_list.gperf"
|
||||
{"uint32_little_endian", &grib_accessor_class_uint32_little_endian},
|
||||
#line 114 "accessor_class_list.gperf"
|
||||
{"global_gaussian", &grib_accessor_class_global_gaussian},
|
||||
|
@ -311,20 +311,20 @@ static const struct accessor_class_hash classes[] =
|
|||
#line 76 "accessor_class_list.gperf"
|
||||
{"divdouble", &grib_accessor_class_divdouble},
|
||||
{""},
|
||||
#line 173 "accessor_class_list.gperf"
|
||||
#line 174 "accessor_class_list.gperf"
|
||||
{"sexagesimal2decimal", &grib_accessor_class_sexagesimal2decimal},
|
||||
#line 99 "accessor_class_list.gperf"
|
||||
{"g2_mars_labeling", &grib_accessor_class_g2_mars_labeling},
|
||||
#line 78 "accessor_class_list.gperf"
|
||||
{"element", &grib_accessor_class_element},
|
||||
#line 158 "accessor_class_list.gperf"
|
||||
#line 159 "accessor_class_list.gperf"
|
||||
{"padtomultiple", &grib_accessor_class_padtomultiple},
|
||||
#line 127 "accessor_class_list.gperf"
|
||||
{"latitudes", &grib_accessor_class_latitudes},
|
||||
#line 162 "accessor_class_list.gperf"
|
||||
#line 163 "accessor_class_list.gperf"
|
||||
{"rdbtime_guess_date", &grib_accessor_class_rdbtime_guess_date},
|
||||
{""}, {""}, {""},
|
||||
#line 192 "accessor_class_list.gperf"
|
||||
#line 193 "accessor_class_list.gperf"
|
||||
{"to_string", &grib_accessor_class_to_string},
|
||||
#line 132 "accessor_class_list.gperf"
|
||||
{"long", &grib_accessor_class_long},
|
||||
|
@ -348,20 +348,20 @@ static const struct accessor_class_hash classes[] =
|
|||
{""},
|
||||
#line 28 "accessor_class_list.gperf"
|
||||
{"bufrdc_expanded_descriptors", &grib_accessor_class_bufrdc_expanded_descriptors},
|
||||
#line 159 "accessor_class_list.gperf"
|
||||
#line 160 "accessor_class_list.gperf"
|
||||
{"position", &grib_accessor_class_position},
|
||||
{""}, {""}, {""},
|
||||
#line 17 "accessor_class_list.gperf"
|
||||
{"blob", &grib_accessor_class_blob},
|
||||
#line 109 "accessor_class_list.gperf"
|
||||
{"gaussian_grid_name", &grib_accessor_class_gaussian_grid_name},
|
||||
#line 195 "accessor_class_list.gperf"
|
||||
#line 196 "accessor_class_list.gperf"
|
||||
{"trim", &grib_accessor_class_trim},
|
||||
{""}, {""},
|
||||
#line 119 "accessor_class_list.gperf"
|
||||
{"ibmfloat", &grib_accessor_class_ibmfloat},
|
||||
{""}, {""},
|
||||
#line 193 "accessor_class_list.gperf"
|
||||
#line 194 "accessor_class_list.gperf"
|
||||
{"transient", &grib_accessor_class_transient},
|
||||
#line 55 "accessor_class_list.gperf"
|
||||
{"data_g1shsimple_packing", &grib_accessor_class_data_g1shsimple_packing},
|
||||
|
@ -370,13 +370,13 @@ static const struct accessor_class_hash classes[] =
|
|||
{"data_g1simple_packing", &grib_accessor_class_data_g1simple_packing},
|
||||
#line 49 "accessor_class_list.gperf"
|
||||
{"data_g1complex_packing", &grib_accessor_class_data_g1complex_packing},
|
||||
#line 164 "accessor_class_list.gperf"
|
||||
#line 165 "accessor_class_list.gperf"
|
||||
{"round", &grib_accessor_class_round},
|
||||
#line 194 "accessor_class_list.gperf"
|
||||
#line 195 "accessor_class_list.gperf"
|
||||
{"transient_darray", &grib_accessor_class_transient_darray},
|
||||
#line 18 "accessor_class_list.gperf"
|
||||
{"budgdate", &grib_accessor_class_budgdate},
|
||||
#line 208 "accessor_class_list.gperf"
|
||||
#line 209 "accessor_class_list.gperf"
|
||||
{"values", &grib_accessor_class_values},
|
||||
#line 143 "accessor_class_list.gperf"
|
||||
{"number_of_coded_values", &grib_accessor_class_number_of_coded_values},
|
||||
|
@ -386,30 +386,30 @@ static const struct accessor_class_hash classes[] =
|
|||
#line 38 "accessor_class_list.gperf"
|
||||
{"concept", &grib_accessor_class_concept},
|
||||
{""},
|
||||
#line 181 "accessor_class_list.gperf"
|
||||
#line 182 "accessor_class_list.gperf"
|
||||
{"spectral_truncation", &grib_accessor_class_spectral_truncation},
|
||||
{""}, {""},
|
||||
#line 83 "accessor_class_list.gperf"
|
||||
{"g1_message_length", &grib_accessor_class_g1_message_length},
|
||||
#line 182 "accessor_class_list.gperf"
|
||||
#line 183 "accessor_class_list.gperf"
|
||||
{"sprintf", &grib_accessor_class_sprintf},
|
||||
#line 188 "accessor_class_list.gperf"
|
||||
#line 189 "accessor_class_list.gperf"
|
||||
{"suppressed", &grib_accessor_class_suppressed},
|
||||
{""},
|
||||
#line 211 "accessor_class_list.gperf"
|
||||
#line 212 "accessor_class_list.gperf"
|
||||
{"when", &grib_accessor_class_when},
|
||||
{""}, {""},
|
||||
#line 178 "accessor_class_list.gperf"
|
||||
#line 179 "accessor_class_list.gperf"
|
||||
{"smart_table", &grib_accessor_class_smart_table},
|
||||
{""},
|
||||
#line 39 "accessor_class_list.gperf"
|
||||
{"constant", &grib_accessor_class_constant},
|
||||
{""}, {""},
|
||||
#line 160 "accessor_class_list.gperf"
|
||||
#line 161 "accessor_class_list.gperf"
|
||||
{"proj_string", &grib_accessor_class_proj_string},
|
||||
#line 149 "accessor_class_list.gperf"
|
||||
{"octet_number", &grib_accessor_class_octet_number},
|
||||
#line 179 "accessor_class_list.gperf"
|
||||
#line 180 "accessor_class_list.gperf"
|
||||
{"smart_table_column", &grib_accessor_class_smart_table_column},
|
||||
{""},
|
||||
#line 135 "accessor_class_list.gperf"
|
||||
|
@ -426,7 +426,7 @@ static const struct accessor_class_hash classes[] =
|
|||
{"data_sh_unpacked", &grib_accessor_class_data_sh_unpacked},
|
||||
#line 27 "accessor_class_list.gperf"
|
||||
{"bufr_string_values", &grib_accessor_class_bufr_string_values},
|
||||
#line 196 "accessor_class_list.gperf"
|
||||
#line 197 "accessor_class_list.gperf"
|
||||
{"uint16", &grib_accessor_class_uint16},
|
||||
{""}, {""},
|
||||
#line 71 "accessor_class_list.gperf"
|
||||
|
@ -439,7 +439,7 @@ static const struct accessor_class_hash classes[] =
|
|||
{""},
|
||||
#line 54 "accessor_class_list.gperf"
|
||||
{"data_g1secondary_bitmap", &grib_accessor_class_data_g1secondary_bitmap},
|
||||
#line 190 "accessor_class_list.gperf"
|
||||
#line 191 "accessor_class_list.gperf"
|
||||
{"to_double", &grib_accessor_class_to_double},
|
||||
#line 101 "accessor_class_list.gperf"
|
||||
{"g2bitmap_present", &grib_accessor_class_g2bitmap_present},
|
||||
|
@ -447,14 +447,14 @@ static const struct accessor_class_hash classes[] =
|
|||
{"ieeefloat", &grib_accessor_class_ieeefloat},
|
||||
#line 150 "accessor_class_list.gperf"
|
||||
{"offset_file", &grib_accessor_class_offset_file},
|
||||
#line 206 "accessor_class_list.gperf"
|
||||
{"validity_date", &grib_accessor_class_validity_date},
|
||||
#line 207 "accessor_class_list.gperf"
|
||||
{"validity_date", &grib_accessor_class_validity_date},
|
||||
#line 208 "accessor_class_list.gperf"
|
||||
{"validity_time", &grib_accessor_class_validity_time},
|
||||
{""},
|
||||
#line 130 "accessor_class_list.gperf"
|
||||
{"library_version", &grib_accessor_class_library_version},
|
||||
#line 210 "accessor_class_list.gperf"
|
||||
#line 211 "accessor_class_list.gperf"
|
||||
{"vector", &grib_accessor_class_vector},
|
||||
#line 84 "accessor_class_list.gperf"
|
||||
{"g1_section4_length", &grib_accessor_class_g1_section4_length},
|
||||
|
@ -467,7 +467,7 @@ static const struct accessor_class_hash classes[] =
|
|||
{""},
|
||||
#line 24 "accessor_class_list.gperf"
|
||||
{"bufr_extract_subsets", &grib_accessor_class_bufr_extract_subsets},
|
||||
#line 157 "accessor_class_list.gperf"
|
||||
#line 158 "accessor_class_list.gperf"
|
||||
{"padtoeven", &grib_accessor_class_padtoeven},
|
||||
#line 50 "accessor_class_list.gperf"
|
||||
{"data_g1second_order_constant_width_packing", &grib_accessor_class_data_g1second_order_constant_width_packing},
|
||||
|
@ -483,7 +483,7 @@ static const struct accessor_class_hash classes[] =
|
|||
#line 21 "accessor_class_list.gperf"
|
||||
{"bufr_elements_table", &grib_accessor_class_bufr_elements_table},
|
||||
{""}, {""}, {""}, {""},
|
||||
#line 152 "accessor_class_list.gperf"
|
||||
#line 153 "accessor_class_list.gperf"
|
||||
{"pack_bufr_values", &grib_accessor_class_pack_bufr_values},
|
||||
#line 35 "accessor_class_list.gperf"
|
||||
{"codetable", &grib_accessor_class_codetable},
|
||||
|
@ -503,12 +503,14 @@ static const struct accessor_class_hash classes[] =
|
|||
{""},
|
||||
#line 33 "accessor_class_list.gperf"
|
||||
{"closest_date", &grib_accessor_class_closest_date},
|
||||
{""}, {""},
|
||||
#line 209 "accessor_class_list.gperf"
|
||||
#line 152 "accessor_class_list.gperf"
|
||||
{"optimal_step_units", &grib_accessor_class_optimal_step_units},
|
||||
{""},
|
||||
#line 210 "accessor_class_list.gperf"
|
||||
{"variable", &grib_accessor_class_variable},
|
||||
#line 133 "accessor_class_list.gperf"
|
||||
{"long_vector", &grib_accessor_class_long_vector},
|
||||
#line 166 "accessor_class_list.gperf"
|
||||
#line 167 "accessor_class_list.gperf"
|
||||
{"scale_values", &grib_accessor_class_scale_values},
|
||||
{""}, {""}, {""},
|
||||
#line 128 "accessor_class_list.gperf"
|
||||
|
@ -533,7 +535,7 @@ static const struct accessor_class_hash classes[] =
|
|||
{""}, {""},
|
||||
#line 41 "accessor_class_list.gperf"
|
||||
{"count_missing", &grib_accessor_class_count_missing},
|
||||
#line 203 "accessor_class_list.gperf"
|
||||
#line 204 "accessor_class_list.gperf"
|
||||
{"unpack_bufr_values", &grib_accessor_class_unpack_bufr_values},
|
||||
{""}, {""},
|
||||
#line 121 "accessor_class_list.gperf"
|
||||
|
@ -598,7 +600,7 @@ static const struct accessor_class_hash classes[] =
|
|||
#line 87 "accessor_class_list.gperf"
|
||||
{"g1day_of_the_year_date", &grib_accessor_class_g1day_of_the_year_date},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
#line 163 "accessor_class_list.gperf"
|
||||
#line 164 "accessor_class_list.gperf"
|
||||
{"reference_value_error", &grib_accessor_class_reference_value_error},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
|
|
|
@ -141,6 +141,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, },
|
||||
{ "packing_type", &grib_accessor_class_packing_type, },
|
||||
{ "pad", &grib_accessor_class_pad, },
|
||||
|
|
|
@ -142,6 +142,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
|
||||
packing_type, &grib_accessor_class_packing_type
|
||||
pad, &grib_accessor_class_pad
|
||||
|
|
|
@ -1004,6 +1004,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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* (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 <map>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <regex>
|
||||
|
||||
#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]?)");
|
||||
std::smatch match;
|
||||
if (std::regex_match(step, match, re)) {
|
||||
if (match.size() == 3) {
|
||||
std::string value = match[1];
|
||||
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");
|
||||
}
|
||||
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<Step> parse_range(const std::string& range_str, const Unit& force_unit)
|
||||
{
|
||||
std::vector<Step> 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), force_unit));
|
||||
prev = pos + 1;
|
||||
}
|
||||
steps.push_back(step_from_string(range_str.substr(prev), force_unit));
|
||||
return steps;
|
||||
}
|
||||
|
||||
bool Step::operator==(const Step& other) const
|
||||
{
|
||||
if ((internal_value_ == other.internal_value_) && (internal_unit_ == other.internal_unit_)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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_);
|
||||
}
|
||||
|
||||
std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endStep)
|
||||
{
|
||||
Step a = startStep;
|
||||
Step b = endStep;
|
||||
|
||||
if (a.internal_value_ == 0 && b.internal_value_ == 0) {
|
||||
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;
|
||||
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 {
|
||||
auto it = std::find_if(Unit::grib_selected_units.begin(), Unit::grib_selected_units.end(), [&](const auto& e) {
|
||||
return e == a.unit().value<Unit::Value>() || e == b.unit().value<Unit::Value>();
|
||||
});
|
||||
|
||||
assert(it != Unit::grib_selected_units.end());
|
||||
|
||||
a.set_unit(*it);
|
||||
b.set_unit(*it);
|
||||
a.recalculateValue();
|
||||
b.recalculateValue();
|
||||
assert(a.internal_unit_ == b.internal_unit_);
|
||||
}
|
||||
|
||||
return {a, b};
|
||||
}
|
||||
|
||||
void Step::init_long(long value, const Unit& unit)
|
||||
{
|
||||
internal_value_ = value;
|
||||
internal_unit_ = unit;
|
||||
unit_ = unit;
|
||||
}
|
||||
|
||||
void Step::init_double(double value, const Unit& unit)
|
||||
{
|
||||
auto seconds = Unit::get_converter().unit_to_duration(unit.value<Unit::Value>());
|
||||
internal_value_ = value * seconds;
|
||||
internal_unit_ = Unit{Unit::Value::SECOND};
|
||||
unit_ = unit;
|
||||
}
|
||||
|
||||
Step& Step::optimize_unit()
|
||||
{
|
||||
if (internal_value_ == 0) {
|
||||
if (unit() > Unit{Unit::Value::HOUR}) {
|
||||
set_unit(Unit{Unit::Value::HOUR});
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
unit_ = internal_unit_;
|
||||
Seconds<long> seconds = to_seconds<long>(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) {
|
||||
long multiplier = Unit::get_converter().unit_to_duration(*it);
|
||||
if (abs_seconds % multiplier == 0) {
|
||||
internal_value_ = seconds.count() / multiplier;
|
||||
internal_unit_ = *it;
|
||||
unit_ = *it;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string Step::value<std::string>(const std::string& format, bool show_hours) 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.
|
||||
|
||||
if (show_hours) {
|
||||
u = unit_.value<std::string>();
|
||||
}
|
||||
else {
|
||||
if (unit_ != Unit::Value::HOUR)
|
||||
u = unit_.value<std::string>();
|
||||
}
|
||||
|
||||
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<double>(), u.c_str());
|
||||
else
|
||||
err = snprintf(output, MAX_SIZE, (format + "%s").c_str(), value<double>(), u.c_str());
|
||||
|
||||
if (err < 0 || err >= MAX_SIZE) {
|
||||
throw std::runtime_error("Error while formatting Step to string");
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace eccodes
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* (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 <tuple>
|
||||
#include <map>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <optional>
|
||||
|
||||
#include "step_unit.h"
|
||||
|
||||
namespace eccodes {
|
||||
class Step {
|
||||
public:
|
||||
// Constructors
|
||||
Step() : internal_value_(0), internal_unit_(Unit::Value::SECOND) {}
|
||||
|
||||
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 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 <typename T> T value() const;
|
||||
template <typename T> T value(const Unit& unit) const;
|
||||
template <typename T> T value(const std::string& format, bool show_hours) const;
|
||||
Unit unit() const { return unit_; }
|
||||
|
||||
// Setters
|
||||
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;
|
||||
bool operator!=(const Step& other) const;
|
||||
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 {
|
||||
Step ret{};
|
||||
ret.internal_value_ = internal_value_;
|
||||
ret.internal_unit_ = internal_unit_;
|
||||
ret.unit_ = unit_;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Methods
|
||||
Step& optimize_unit();
|
||||
friend std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endStep);
|
||||
|
||||
|
||||
private:
|
||||
void init_long(long value, const Unit& unit);
|
||||
void init_double(double value, const Unit& unit);
|
||||
Step& recalculateValue() {
|
||||
if (internal_value_ == 0) {
|
||||
internal_unit_ = unit_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Seconds<long> seconds = to_seconds<long>(internal_value_, internal_unit_);
|
||||
long multiplier = Unit::get_converter().unit_to_duration(unit_.value<Unit::Value>());
|
||||
internal_value_ = seconds.count() / multiplier;
|
||||
internal_unit_ = unit_;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
long internal_value_;
|
||||
Unit internal_unit_;
|
||||
Unit unit_;
|
||||
};
|
||||
|
||||
|
||||
Step step_from_string(const std::string& step, const Unit& force_unit);
|
||||
std::vector<Step> parse_range(const std::string& range_str, const Unit& force_unit);
|
||||
std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endStep);
|
||||
|
||||
|
||||
template <typename T> T Step::value() const {
|
||||
if (internal_value_ == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (internal_unit_ == unit_) {
|
||||
return internal_value_;
|
||||
}
|
||||
Seconds<T> seconds = to_seconds<T>(internal_value_, internal_unit_);
|
||||
T value = from_seconds<T>(seconds, unit_);
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T> T Step::value(const Unit& unit) const {
|
||||
if (internal_value_ == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (internal_unit_ == unit) {
|
||||
return internal_value_;
|
||||
}
|
||||
Seconds<T> seconds = to_seconds<T>(internal_value_, internal_unit_);
|
||||
T value = from_seconds<T>(seconds, unit);
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace eccodes
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* (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"
|
||||
|
||||
namespace eccodes {
|
||||
|
||||
Unit::Map Unit::map_{};
|
||||
|
||||
std::vector<Unit::Value> Unit::grib_selected_units = {
|
||||
Unit::Value::SECOND,
|
||||
Unit::Value::MINUTE,
|
||||
Unit::Value::HOUR,
|
||||
};
|
||||
|
||||
std::vector<Unit::Value> 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
|
||||
};
|
||||
|
||||
template <> long Unit::value<long>() const {
|
||||
return map_.unit_to_long(internal_value_);
|
||||
}
|
||||
|
||||
template <> Unit::Value Unit::value<Unit::Value>() const {
|
||||
return internal_value_;
|
||||
}
|
||||
|
||||
template <> std::string Unit::value<std::string>() const {
|
||||
return map_.unit_to_name(internal_value_);
|
||||
}
|
||||
|
||||
} // namespace eccodes
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* (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 <chrono>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
|
||||
namespace eccodes {
|
||||
|
||||
template <typename T> using Minutes = std::chrono::duration<T, std::ratio<60>>;
|
||||
template <typename T> using Hours = std::chrono::duration<T, std::ratio<3600>>;
|
||||
template <typename T> using Days = std::chrono::duration<T, std::ratio<86400>>;
|
||||
template <typename T> using Months = std::chrono::duration<T, std::ratio<2592000>>;
|
||||
template <typename T> using Years = std::chrono::duration<T, std::ratio<31536000>>;
|
||||
template <typename T> using Years10 = std::chrono::duration<T, std::ratio<315360000>>;
|
||||
template <typename T> using Years30 = std::chrono::duration<T, std::ratio<946080000>>;
|
||||
template <typename T> using Centuries = std::chrono::duration<T, std::ratio<3153600000>>;
|
||||
template <typename T> using Hours3 = std::chrono::duration<T, std::ratio<10800>>;
|
||||
template <typename T> using Hours6 = std::chrono::duration<T, std::ratio<21600>>;
|
||||
template <typename T> using Hours12 = std::chrono::duration<T, std::ratio<43200>>;
|
||||
template <typename T> using Seconds = std::chrono::duration<T, std::ratio<1>>;
|
||||
template <typename T> using Minutes15 = std::chrono::duration<T, std::ratio<900>>;
|
||||
template <typename T> using Minutes30 = std::chrono::duration<T, std::ratio<1800>>;
|
||||
template <typename T> using Missing = std::chrono::duration<T, std::ratio<0>>;
|
||||
|
||||
|
||||
|
||||
class Unit;
|
||||
template <typename T> Seconds<T> to_seconds(long value, const Unit& unit);
|
||||
template <typename T> T from_seconds(Seconds<T> seconds, const Unit& unit);
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
Unit() : internal_value_(Value::HOUR) {}
|
||||
|
||||
explicit Unit(Value unit_value) : internal_value_(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 "} + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
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 "} + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
template <typename T> T value() const;
|
||||
static std::vector<Value> grib_selected_units;
|
||||
static std::vector<Value> complete_unit_order_;
|
||||
|
||||
static std::vector<Unit> list_supported_units() {
|
||||
std::vector<Unit> result;
|
||||
result.reserve(32);
|
||||
for (const auto& val : complete_unit_order_) {
|
||||
if (val == Value::MISSING)
|
||||
continue;
|
||||
result.push_back(Unit(val));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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<long>(entry.unit_value);
|
||||
long_to_value_[static_cast<long>(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
|
||||
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
|
||||
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 {
|
||||
Value unit_value;
|
||||
std::string unit_name;
|
||||
uint64_t duration;
|
||||
};
|
||||
|
||||
const std::array<Entry, 15> 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<std::string, Value> name_to_value_;
|
||||
std::unordered_map<Value, std::string> value_to_name_;
|
||||
|
||||
std::unordered_map<Value, long> value_to_long_;
|
||||
std::unordered_map<long, Value> long_to_value_;
|
||||
|
||||
std::unordered_map<Value, uint64_t> value_to_duration_;
|
||||
std::unordered_map<uint64_t, Value> duration_to_value_;
|
||||
};
|
||||
|
||||
|
||||
Value internal_value_;
|
||||
static Map map_;
|
||||
public:
|
||||
static Map& get_converter() {return map_;}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
Seconds<T> to_seconds(long value, const Unit& unit) {
|
||||
Seconds<T> seconds;
|
||||
switch (unit.value<Unit::Value>()) {
|
||||
case Unit::Value::SECOND: seconds = Seconds<T>(value); break;
|
||||
case Unit::Value::MINUTE: seconds = Minutes<T>(value); break;
|
||||
case Unit::Value::MINUTES15: seconds = Minutes15<T>(value); break;
|
||||
case Unit::Value::MINUTES30: seconds = Minutes30<T>(value); break;
|
||||
case Unit::Value::HOUR: seconds = Hours<T>(value); break;
|
||||
case Unit::Value::HOURS3: seconds = Hours3<T>(value); break;
|
||||
case Unit::Value::HOURS6: seconds = Hours6<T>(value); break;
|
||||
case Unit::Value::HOURS12: seconds = Hours12<T>(value); break;
|
||||
case Unit::Value::DAY: seconds = Days<T>(value); break;
|
||||
case Unit::Value::MONTH: seconds = Months<T>(value); break;
|
||||
case Unit::Value::YEAR: seconds = Years<T>(value); break;
|
||||
case Unit::Value::YEARS10: seconds = Years10<T>(value); break;
|
||||
case Unit::Value::YEARS30: seconds = Years30<T>(value); break;
|
||||
case Unit::Value::CENTURY: seconds = Centuries<T>(value); break;
|
||||
default:
|
||||
std::string msg = "Unknown unit: " + unit.value<std::string>();
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
return seconds;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
T from_seconds(Seconds<T> seconds, const Unit& unit) {
|
||||
T value;
|
||||
switch (unit.value<Unit::Value>()) {
|
||||
case Unit::Value::SECOND: value = std::chrono::duration_cast<Seconds<T>>(seconds).count(); break;
|
||||
case Unit::Value::MINUTE: value = std::chrono::duration_cast<Minutes<T>>(seconds).count(); break;
|
||||
case Unit::Value::MINUTES15: value = std::chrono::duration_cast<Minutes15<T>>(seconds).count(); break;
|
||||
case Unit::Value::MINUTES30: value = std::chrono::duration_cast<Minutes30<T>>(seconds).count(); break;
|
||||
case Unit::Value::HOUR: value = std::chrono::duration_cast<Hours<T>>(seconds).count(); break;
|
||||
case Unit::Value::HOURS3: value = std::chrono::duration_cast<Hours3<T>>(seconds).count(); break;
|
||||
case Unit::Value::HOURS6: value = std::chrono::duration_cast<Hours6<T>>(seconds).count(); break;
|
||||
case Unit::Value::HOURS12: value = std::chrono::duration_cast<Hours12<T>>(seconds).count(); break;
|
||||
case Unit::Value::DAY: value = std::chrono::duration_cast<Days<T>>(seconds).count(); break;
|
||||
case Unit::Value::MONTH: value = std::chrono::duration_cast<Months<T>>(seconds).count(); break;
|
||||
case Unit::Value::YEAR: value = std::chrono::duration_cast<Years<T>>(seconds).count(); break;
|
||||
case Unit::Value::YEARS10: value = std::chrono::duration_cast<Years10<T>>(seconds).count(); break;
|
||||
case Unit::Value::YEARS30: value = std::chrono::duration_cast<Years30<T>>(seconds).count(); break;
|
||||
case Unit::Value::CENTURY: value = std::chrono::duration_cast<Centuries<T>>(seconds).count(); break;
|
||||
default:
|
||||
std::string msg = "Unknown unit: " + unit.value<std::string>();
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace eccodes
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* (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 <type_traits>
|
||||
|
||||
std::optional<eccodes::Step> 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;
|
||||
if (grib_get_long_internal(h, unit_key, &unit) != GRIB_SUCCESS)
|
||||
return {};
|
||||
|
||||
long value = 0;
|
||||
if (grib_get_long_internal(h, value_key, &value) != GRIB_SUCCESS)
|
||||
return {};
|
||||
|
||||
return eccodes::Step(value, unit);
|
||||
}
|
||||
else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
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<long>())) != GRIB_SUCCESS)
|
||||
return err;
|
||||
if ((err = grib_set_long_internal(h, unit_key.c_str(), step.unit().value<long>())) != GRIB_SUCCESS)
|
||||
return err;
|
||||
return GRIB_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* (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"
|
||||
#include "step.h"
|
||||
#include <optional>
|
||||
|
||||
std::optional<eccodes::Step> 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);
|
|
@ -248,6 +248,7 @@ if( HAVE_BUILD_TOOLS )
|
|||
grib_ecc-1397
|
||||
grib_ecc-1425
|
||||
grib_ecc-1467
|
||||
grib_sub_hourly
|
||||
grib_set_bytes
|
||||
grib_set_force
|
||||
bufr_ecc-556
|
||||
|
|
|
@ -147,7 +147,7 @@ ${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 "Unit not found" $temp
|
||||
|
||||
set +e
|
||||
${tools_dir}/grib_set -s centre=ECMF $input $outfile > $temp 2>&1
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,486 @@
|
|||
#!/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
|
||||
|
||||
# See JIRA issues ECC-1620, ECC-1238
|
||||
# -----------------------------------
|
||||
|
||||
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
|
||||
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'"
|
||||
${tools_dir}/grib_dump -O $a_file | grep -E "indicatorOfUnitOfTimeRange|lengthOfTimeRange|indicatorOfUnitForTimeRange|forecastTime"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
HOUR=""
|
||||
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_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
|
||||
accumulated_field=$data_dir/reduced_gaussian_sub_area.grib2
|
||||
|
||||
|
||||
#### 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=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"
|
||||
|
||||
|
||||
#### 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"
|
||||
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$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$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$HOUR"
|
||||
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$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$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$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"
|
||||
|
||||
|
||||
#### CHECK units
|
||||
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"
|
||||
|
||||
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" "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$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"
|
||||
|
||||
${tools_dir}/grib_set -s stepUnits=s,startStep=0,endStep=345600 $fn $temp
|
||||
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 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 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 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 D 4 D"
|
||||
|
||||
|
||||
#### CHECK negative forecastTime
|
||||
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"
|
||||
|
||||
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$HOUR"
|
||||
|
||||
|
||||
#### CHECK: check optimal units are set correctly in GRIB files
|
||||
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" "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" "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" "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" "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" "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="$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"
|
||||
#${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 $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 "-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
|
||||
|
||||
#### CHECK: grib_set - endStep + stepUnits
|
||||
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"
|
||||
|
||||
# Use range unit: hour
|
||||
${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(maee) add to tests
|
||||
grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 6 h"
|
||||
|
||||
# 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=88200s $temp $temp2
|
||||
grib_check_key_equals $temp2 "-p $low_level_keys" "1440 m 30 m"
|
||||
|
||||
${tools_dir}/grib_set -s endStep:s=24024 $temp $temp2
|
||||
grib_check_key_equals $temp2 "-p $low_level_keys" "24 h 24000 h"
|
||||
|
||||
${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:s=5h $temp $temp2
|
||||
grib_check_key_equals $temp2 "-p $low_level_keys" "5 h 43 h"
|
||||
|
||||
${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=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$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$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$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"
|
||||
grib_check_key_equals $temp2 "-p stepRange:s" "1m-2m"
|
||||
|
||||
${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 -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$HOUR-2928$HOUR"
|
||||
|
||||
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 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" # 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.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" # 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" # not supported
|
||||
|
||||
|
||||
|
||||
|
||||
${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m $fn $temp
|
||||
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="$instantaneous_field"
|
||||
low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s"
|
||||
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__" "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" "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$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$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"
|
||||
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__" "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"
|
||||
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$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"
|
||||
|
||||
${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__" "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"
|
||||
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$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$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"
|
||||
|
||||
|
||||
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="$accumulated_field"
|
||||
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$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$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$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"
|
||||
|
||||
${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 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"
|
||||
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$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$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$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$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"
|
||||
|
||||
cat >$tempFilt<<EOF
|
||||
set stepUnits="m"; print "[step]";
|
||||
EOF
|
||||
${tools_dir}/grib_filter $tempFilt $data_dir/constant_field.grib2
|
||||
|
||||
|
||||
cat >$tempFilt<<EOF
|
||||
set stepUnits="s"; print "[step]";
|
||||
EOF
|
||||
${tools_dir}/grib_filter $tempFilt $data_dir/constant_field.grib2
|
||||
|
||||
|
||||
|
||||
rm -f $temp $temp2 $tempFilt
|
||||
|
||||
#~/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
|
Loading…
Reference in New Issue