mirror of https://github.com/ecmwf/eccodes.git
679 lines
23 KiB
C++
679 lines
23 KiB
C++
/*
|
|
* (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.
|
|
*/
|
|
|
|
/***************************************************************************
|
|
* Jean Baptiste Filippi - 01.11.2005 *
|
|
* Enrico Fucile *
|
|
* Shahram Najm *
|
|
***************************************************************************/
|
|
#include "grib_api_internal.h"
|
|
#include "grib_value.h"
|
|
#include <limits>
|
|
#include <cassert>
|
|
|
|
/*
|
|
This is used by make_class.pl
|
|
|
|
START_CLASS_DEF
|
|
CLASS = accessor
|
|
IMPLEMENTS = unpack_long;pack_long; clear
|
|
IMPLEMENTS = unpack_double;pack_double;unpack_double_element;unpack_double_element_set
|
|
IMPLEMENTS = unpack_float
|
|
IMPLEMENTS = unpack_string;pack_string
|
|
IMPLEMENTS = unpack_string_array;pack_string_array
|
|
IMPLEMENTS = unpack_bytes;pack_bytes
|
|
IMPLEMENTS = unpack_double_subarray
|
|
IMPLEMENTS = init;dump;destroy;string_length
|
|
IMPLEMENTS = get_native_type;sub_section
|
|
IMPLEMENTS = next_offset;value_count;byte_offset;byte_count
|
|
IMPLEMENTS = notify_change;pack_expression
|
|
IMPLEMENTS = update_size; next; preferred_size
|
|
IMPLEMENTS = compare;is_missing;make_clone
|
|
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 grib_section* sub_section(grib_accessor* a);
|
|
static int get_native_type(grib_accessor*);
|
|
static int is_missing(grib_accessor*);
|
|
static int pack_bytes(grib_accessor*, const unsigned char*, size_t* len);
|
|
static int pack_double(grib_accessor*, const double* val, size_t* len);
|
|
static int pack_long(grib_accessor*, const long* val, size_t* len);
|
|
static int pack_string(grib_accessor*, const char*, size_t* len);
|
|
static int pack_string_array(grib_accessor*, const char**, size_t* len);
|
|
static int pack_expression(grib_accessor*, grib_expression*);
|
|
static int unpack_bytes(grib_accessor*, unsigned char*, size_t* len);
|
|
static int unpack_double(grib_accessor*, double* val, size_t* len);
|
|
static int unpack_float(grib_accessor*, float* 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 int unpack_string_array(grib_accessor*, char**, size_t* len);
|
|
static size_t string_length(grib_accessor*);
|
|
static long byte_count(grib_accessor*);
|
|
static long byte_offset(grib_accessor*);
|
|
static long next_offset(grib_accessor*);
|
|
static int value_count(grib_accessor*, long*);
|
|
static void destroy(grib_context*, grib_accessor*);
|
|
static void dump(grib_accessor*, grib_dumper*);
|
|
static void init(grib_accessor*, const long, grib_arguments*);
|
|
static int notify_change(grib_accessor*, grib_accessor*);
|
|
static void update_size(grib_accessor*, size_t);
|
|
static size_t preferred_size(grib_accessor*, int);
|
|
static grib_accessor* next(grib_accessor*, int);
|
|
static int compare(grib_accessor*, grib_accessor*);
|
|
static int unpack_double_element(grib_accessor*, size_t i, double* val);
|
|
static int unpack_double_element_set(grib_accessor*, const size_t* index_array, size_t len, double* val_array);
|
|
static int unpack_double_subarray(grib_accessor*, double* val, size_t start, size_t len);
|
|
static int clear(grib_accessor*);
|
|
static grib_accessor* make_clone(grib_accessor*, grib_section*, int*);
|
|
|
|
typedef struct grib_accessor_gen
|
|
{
|
|
grib_accessor att;
|
|
/* Members defined in gen */
|
|
} grib_accessor_gen;
|
|
|
|
|
|
static grib_accessor_class _grib_accessor_class_gen = {
|
|
0, /* super */
|
|
"gen", /* name */
|
|
sizeof(grib_accessor_gen), /* size */
|
|
0, /* inited */
|
|
0, /* init_class */
|
|
&init, /* init */
|
|
0, /* post_init */
|
|
&destroy, /* destroy */
|
|
&dump, /* dump */
|
|
&next_offset, /* next_offset */
|
|
&string_length, /* get length of string */
|
|
&value_count, /* get number of values */
|
|
&byte_count, /* get number of bytes */
|
|
&byte_offset, /* get offset to bytes */
|
|
&get_native_type, /* get native type */
|
|
&sub_section, /* get sub_section */
|
|
0, /* pack_missing */
|
|
&is_missing, /* is_missing */
|
|
&pack_long, /* pack_long */
|
|
&unpack_long, /* unpack_long */
|
|
&pack_double, /* pack_double */
|
|
0, /* pack_float */
|
|
&unpack_double, /* unpack_double */
|
|
&unpack_float, /* unpack_float */
|
|
&pack_string, /* pack_string */
|
|
&unpack_string, /* unpack_string */
|
|
&pack_string_array, /* pack_string_array */
|
|
&unpack_string_array, /* unpack_string_array */
|
|
&pack_bytes, /* pack_bytes */
|
|
&unpack_bytes, /* unpack_bytes */
|
|
&pack_expression, /* pack_expression */
|
|
¬ify_change, /* notify_change */
|
|
&update_size, /* update_size */
|
|
&preferred_size, /* preferred_size */
|
|
0, /* resize */
|
|
0, /* nearest_smaller_value */
|
|
&next, /* next accessor */
|
|
&compare, /* compare vs. another accessor */
|
|
&unpack_double_element, /* unpack only ith value (double) */
|
|
0, /* unpack only ith value (float) */
|
|
&unpack_double_element_set, /* unpack a given set of elements (double) */
|
|
0, /* unpack a given set of elements (float) */
|
|
&unpack_double_subarray, /* unpack a subarray */
|
|
&clear, /* clear */
|
|
&make_clone, /* clone accessor */
|
|
};
|
|
|
|
|
|
grib_accessor_class* grib_accessor_class_gen = &_grib_accessor_class_gen;
|
|
|
|
/* END_CLASS_IMP */
|
|
|
|
static void init(grib_accessor* a, const long len, grib_arguments* param)
|
|
{
|
|
grib_action* act = (grib_action*)(a->creator);
|
|
if (a->flags & GRIB_ACCESSOR_FLAG_TRANSIENT) {
|
|
a->length = 0;
|
|
if (!a->vvalue)
|
|
a->vvalue = (grib_virtual_value*)grib_context_malloc_clear(a->context, sizeof(grib_virtual_value));
|
|
a->vvalue->type = grib_accessor_get_native_type(a);
|
|
a->vvalue->length = len;
|
|
if (act->default_value != NULL) {
|
|
const char* p = 0;
|
|
size_t s_len = 1;
|
|
long l;
|
|
int ret = 0;
|
|
double d;
|
|
char tmp[1024];
|
|
grib_expression* expression = grib_arguments_get_expression(grib_handle_of_accessor(a), act->default_value, 0);
|
|
int type = grib_expression_native_type(grib_handle_of_accessor(a), expression);
|
|
switch (type) {
|
|
case GRIB_TYPE_DOUBLE:
|
|
grib_expression_evaluate_double(grib_handle_of_accessor(a), expression, &d);
|
|
grib_pack_double(a, &d, &s_len);
|
|
break;
|
|
|
|
case GRIB_TYPE_LONG:
|
|
grib_expression_evaluate_long(grib_handle_of_accessor(a), expression, &l);
|
|
grib_pack_long(a, &l, &s_len);
|
|
break;
|
|
|
|
default:
|
|
s_len = sizeof(tmp);
|
|
p = grib_expression_evaluate_string(grib_handle_of_accessor(a), expression, tmp, &s_len, &ret);
|
|
if (ret != GRIB_SUCCESS) {
|
|
grib_context_log(a->context, GRIB_LOG_ERROR, "Unable to evaluate %s as string", a->name);
|
|
Assert(0);
|
|
}
|
|
s_len = strlen(p) + 1;
|
|
grib_pack_string(a, p, &s_len);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
a->length = len;
|
|
}
|
|
}
|
|
|
|
static void dump(grib_accessor* a, grib_dumper* dumper)
|
|
{
|
|
const int type = grib_accessor_get_native_type(a);
|
|
switch (type) {
|
|
case GRIB_TYPE_STRING:
|
|
grib_dump_string(dumper, a, NULL);
|
|
break;
|
|
case GRIB_TYPE_DOUBLE:
|
|
grib_dump_double(dumper, a, NULL);
|
|
break;
|
|
case GRIB_TYPE_LONG:
|
|
grib_dump_long(dumper, a, NULL);
|
|
break;
|
|
default:
|
|
grib_dump_bytes(dumper, a, NULL);
|
|
}
|
|
}
|
|
|
|
static long next_offset(grib_accessor* a)
|
|
{
|
|
return a->offset + a->length;
|
|
}
|
|
|
|
static int value_count(grib_accessor* a, long* count)
|
|
{
|
|
*count = 1;
|
|
return 0;
|
|
}
|
|
|
|
static size_t string_length(grib_accessor* a)
|
|
{
|
|
return 1024;
|
|
}
|
|
|
|
static long byte_count(grib_accessor* a)
|
|
{
|
|
return a->length;
|
|
}
|
|
|
|
static int get_native_type(grib_accessor* a)
|
|
{
|
|
grib_context_log(a->context, GRIB_LOG_ERROR,
|
|
"Accessor %s [%s] must implement 'get_native_type'", a->name, a->cclass->name);
|
|
return GRIB_TYPE_UNDEFINED;
|
|
}
|
|
|
|
static long byte_offset(grib_accessor* a)
|
|
{
|
|
return a->offset;
|
|
}
|
|
|
|
static int unpack_bytes(grib_accessor* a, unsigned char* val, size_t* len)
|
|
{
|
|
unsigned char* buf = grib_handle_of_accessor(a)->buffer->data;
|
|
const long length = grib_byte_count(a);
|
|
const long offset = grib_byte_offset(a);
|
|
|
|
if (*len < length) {
|
|
grib_context_log(a->context, GRIB_LOG_ERROR, "Wrong size for %s, it is %ld bytes long", a->name, length);
|
|
*len = length;
|
|
return GRIB_ARRAY_TOO_SMALL;
|
|
}
|
|
|
|
memcpy(val, buf + offset, length);
|
|
*len = length;
|
|
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
static int clear(grib_accessor* a)
|
|
{
|
|
unsigned char* buf = grib_handle_of_accessor(a)->buffer->data;
|
|
const long length = grib_byte_count(a);
|
|
const long offset = grib_byte_offset(a);
|
|
|
|
memset(buf + offset, 0, length);
|
|
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
static int unpack_long(grib_accessor* a, long* v, size_t* len)
|
|
{
|
|
int type = GRIB_TYPE_UNDEFINED;
|
|
if (a->cclass->unpack_double && a->cclass->unpack_double != &unpack_double) {
|
|
double val = 0.0;
|
|
size_t l = 1;
|
|
grib_unpack_double(a, &val, &l);
|
|
if (val == GRIB_MISSING_DOUBLE)
|
|
*v = GRIB_MISSING_LONG;
|
|
else
|
|
*v = (long)val;
|
|
grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting double %s to long", a->name);
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
if (a->cclass->unpack_string && a->cclass->unpack_string != &unpack_string) {
|
|
char val[1024];
|
|
size_t l = sizeof(val);
|
|
char* last = NULL;
|
|
grib_unpack_string(a, val, &l);
|
|
|
|
*v = strtol(val, &last, 10);
|
|
|
|
if (*last == 0) {
|
|
grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting string %s to long", a->name);
|
|
return GRIB_SUCCESS;
|
|
}
|
|
}
|
|
|
|
grib_context_log(a->context, GRIB_LOG_ERROR, "Cannot unpack key '%s' as long", a->name);
|
|
if (grib_get_native_type(grib_handle_of_accessor(a), a->name, &type) == GRIB_SUCCESS) {
|
|
grib_context_log(a->context, GRIB_LOG_ERROR, "Hint: Try unpacking as %s", grib_get_type_name(type));
|
|
}
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
template <typename T>
|
|
static int unpack(grib_accessor* a, T* v, size_t* len)
|
|
{
|
|
static_assert(std::is_floating_point<T>::value, "Requires floating point numbers");
|
|
int type = GRIB_TYPE_UNDEFINED;
|
|
const char* Tname = type_to_string<T>(*v);
|
|
if (a->cclass->unpack_long && a->cclass->unpack_long != &unpack_long) {
|
|
long val = 0;
|
|
size_t l = 1;
|
|
grib_unpack_long(a, &val, &l);
|
|
*v = val;
|
|
grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting long %s to %s", a->name, Tname);
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
if (a->cclass->unpack_string && a->cclass->unpack_string != &unpack_string) {
|
|
char val[1024];
|
|
size_t l = sizeof(val);
|
|
char* last = NULL;
|
|
grib_unpack_string(a, val, &l);
|
|
|
|
*v = strtod(val, &last);
|
|
if (*last == 0) { /* conversion of string to double worked */
|
|
grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting string %s to %s", a->name, Tname);
|
|
return GRIB_SUCCESS;
|
|
}
|
|
}
|
|
|
|
grib_context_log(a->context, GRIB_LOG_ERROR, "Cannot unpack key '%s' as %s", a->name, Tname);
|
|
if (grib_get_native_type(grib_handle_of_accessor(a), a->name, &type) == GRIB_SUCCESS) {
|
|
grib_context_log(a->context, GRIB_LOG_ERROR, "Hint: Try unpacking as %s", grib_get_type_name(type));
|
|
}
|
|
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int unpack_double(grib_accessor* a, double* v, size_t* len)
|
|
{
|
|
return unpack<double>(a, v, len);
|
|
}
|
|
|
|
static int unpack_float(grib_accessor* a, float* v, size_t* len)
|
|
{
|
|
return unpack<float>(a, v, len);
|
|
}
|
|
|
|
static int unpack_string(grib_accessor* a, char* v, size_t* len)
|
|
{
|
|
int err = 0;
|
|
if (a->cclass->unpack_double && a->cclass->unpack_double != &unpack_double) {
|
|
double val = 0.0;
|
|
size_t l = 1;
|
|
err = grib_unpack_double(a, &val, &l);
|
|
if (err) return err;
|
|
snprintf(v, 64, "%g", val);
|
|
*len = strlen(v);
|
|
grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting double %s to string", a->name);
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
if (a->cclass->unpack_long && a->cclass->unpack_long != &unpack_long) {
|
|
long val = 0;
|
|
size_t l = 1;
|
|
err = grib_unpack_long(a, &val, &l);
|
|
if (err) return err;
|
|
snprintf(v, 64, "%ld", val);
|
|
*len = strlen(v);
|
|
grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting long %s to string\n", a->name);
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int unpack_string_array(grib_accessor* a, char** v, size_t* len)
|
|
{
|
|
size_t length = 0;
|
|
|
|
int err = ecc__grib_get_string_length(a, &length);
|
|
if (err)
|
|
return err;
|
|
v[0] = (char*)grib_context_malloc_clear(a->context, length);
|
|
grib_unpack_string(a, v[0], &length); // TODO(masn): check return value
|
|
*len = 1;
|
|
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
static int pack_expression(grib_accessor* a, grib_expression* e)
|
|
{
|
|
size_t len = 1;
|
|
long lval = 0;
|
|
double dval = 0;
|
|
const char* cval = NULL;
|
|
int ret = 0;
|
|
grib_handle* hand = grib_handle_of_accessor(a);
|
|
|
|
// Use the native type of the expression not the accessor
|
|
switch (grib_expression_native_type(hand, e)) {
|
|
case GRIB_TYPE_LONG: {
|
|
len = 1;
|
|
ret = grib_expression_evaluate_long(hand, e, &lval);
|
|
if (ret != GRIB_SUCCESS) {
|
|
grib_context_log(a->context, GRIB_LOG_ERROR, "Unable to set %s as long (from %s)",
|
|
a->name, e->cclass->name);
|
|
return ret;
|
|
}
|
|
/*if (hand->context->debug)
|
|
printf("ECCODES DEBUG grib_accessor_class_gen::pack_expression %s %ld\n", a->name,lval);*/
|
|
return grib_pack_long(a, &lval, &len);
|
|
}
|
|
|
|
case GRIB_TYPE_DOUBLE: {
|
|
len = 1;
|
|
ret = grib_expression_evaluate_double(hand, e, &dval);
|
|
if (ret != GRIB_SUCCESS) {
|
|
grib_context_log(a->context, GRIB_LOG_ERROR, "Unable to set %s as double (from %s)",
|
|
a->name, e->cclass->name);
|
|
return ret;
|
|
}
|
|
/*if (hand->context->debug)
|
|
printf("ECCODES DEBUG grib_accessor_class_gen::pack_expression %s %g\n", a->name, dval);*/
|
|
return grib_pack_double(a, &dval, &len);
|
|
}
|
|
|
|
case GRIB_TYPE_STRING: {
|
|
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, "Unable to set %s as string (from %s)",
|
|
a->name, e->cclass->name);
|
|
return ret;
|
|
}
|
|
len = strlen(cval);
|
|
/*if (hand->context->debug)
|
|
printf("ECCODES DEBUG grib_accessor_class_gen::pack_expression %s %s\n", a->name, cval);*/
|
|
return grib_pack_string(a, cval, &len);
|
|
}
|
|
}
|
|
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int pack_long(grib_accessor* a, const long* v, size_t* len)
|
|
{
|
|
grib_context* c = a->context;
|
|
if (a->cclass->pack_double && a->cclass->pack_double != &pack_double) {
|
|
int i = 0, ret = 0;
|
|
double* val = (double*)grib_context_malloc(c, *len * (sizeof(double)));
|
|
if (!val) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"Unable to allocate %zu bytes", *len * (sizeof(double)));
|
|
return GRIB_OUT_OF_MEMORY;
|
|
}
|
|
for (i = 0; i < *len; i++)
|
|
val[i] = (long)v[i];
|
|
ret = grib_pack_double(a, val, len);
|
|
grib_context_free(c, val);
|
|
return ret;
|
|
}
|
|
grib_context_log(c, GRIB_LOG_ERROR, "Should not pack '%s' as an integer", a->name);
|
|
if (a->cclass->pack_string && a->cclass->pack_string != &pack_string) {
|
|
grib_context_log(c, GRIB_LOG_ERROR, "Try packing as a string");
|
|
}
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int pack_double_array_as_long(grib_accessor* a, const double* v, size_t* len)
|
|
{
|
|
grib_context* c = a->context;
|
|
int ret = GRIB_SUCCESS;
|
|
size_t i = 0;
|
|
size_t numBytes = *len * (sizeof(long));
|
|
long* lValues = (long*)grib_context_malloc(c, numBytes);
|
|
if (!lValues) {
|
|
grib_context_log(c, GRIB_LOG_ERROR, "Unable to allocate %ld bytes", numBytes);
|
|
return GRIB_OUT_OF_MEMORY;
|
|
}
|
|
for (i = 0; i < *len; i++)
|
|
lValues[i] = (long)v[i]; /* convert from double to long */
|
|
ret = grib_pack_long(a, lValues, len);
|
|
grib_context_free(c, lValues);
|
|
return ret;
|
|
}
|
|
|
|
static int pack_double(grib_accessor* a, const double* v, size_t* len)
|
|
{
|
|
int do_pack_as_long = 0;
|
|
grib_context* c = a->context;
|
|
if (a->cclass->pack_long && a->cclass->pack_long != &pack_long) {
|
|
do_pack_as_long = 1;
|
|
}
|
|
else {
|
|
/* ECC-648: Special case of codetable */
|
|
if (strcmp(a->cclass->name, "codetable") == 0) {
|
|
do_pack_as_long = 1;
|
|
}
|
|
}
|
|
if (do_pack_as_long) {
|
|
return pack_double_array_as_long(a, v, len);
|
|
}
|
|
grib_context_log(c, GRIB_LOG_ERROR, "Should not pack '%s' as a double", a->name);
|
|
if (a->cclass->pack_string && a->cclass->pack_string != &pack_string) {
|
|
grib_context_log(c, GRIB_LOG_ERROR, "Try packing as a string");
|
|
}
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int pack_string_array(grib_accessor* a, const char** v, size_t* len)
|
|
{
|
|
int err = 0;
|
|
size_t length = 0;
|
|
grib_accessor* as = 0;
|
|
|
|
as = a;
|
|
long i = (long)*len - 1;
|
|
while (as && i >= 0) {
|
|
length = strlen(v[i]);
|
|
err = grib_pack_string(as, v[i], &length);
|
|
if (err)
|
|
return err;
|
|
--i;
|
|
as = as->same;
|
|
}
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
static int pack_string(grib_accessor* a, const char* v, size_t* len)
|
|
{
|
|
if (a->cclass->pack_double && a->cclass->pack_double != &pack_double) {
|
|
size_t l = 1;
|
|
char* endPtr = NULL; /* for error handling */
|
|
double val = strtod(v, &endPtr);
|
|
if (*endPtr) {
|
|
grib_context_log(a->context, GRIB_LOG_ERROR,
|
|
"%s: Invalid value (%s) for key '%s'. String cannot be converted to a double",
|
|
__func__, v, a->name);
|
|
return GRIB_WRONG_TYPE;
|
|
}
|
|
return grib_pack_double(a, &val, &l);
|
|
}
|
|
|
|
if (a->cclass->pack_long && a->cclass->pack_long != &pack_long) {
|
|
size_t l = 1;
|
|
long val = atol(v);
|
|
return grib_pack_long(a, &val, &l);
|
|
}
|
|
|
|
grib_context_log(a->context, GRIB_LOG_ERROR, "Should not pack '%s' as string", a->name);
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int pack_bytes(grib_accessor* a, const unsigned char* val, size_t* len)
|
|
{
|
|
const size_t length = *len;
|
|
if (length != a->length) {
|
|
grib_context_log(a->context, GRIB_LOG_ERROR,
|
|
"pack_bytes: Wrong size (%zu) for %s. It is %ld bytes long",
|
|
length, a->name, a->length);
|
|
return GRIB_BUFFER_TOO_SMALL;
|
|
}
|
|
grib_buffer_replace(a, val, length, 1, 1);
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
static void destroy(grib_context* ct, grib_accessor* a)
|
|
{
|
|
grib_dependency_remove_observed(a);
|
|
grib_dependency_remove_observer(a);
|
|
if (a->vvalue != NULL) {
|
|
grib_context_free(ct, a->vvalue);
|
|
a->vvalue = NULL;
|
|
}
|
|
/*grib_context_log(ct,GRIB_LOG_DEBUG,"address=%p",a);*/
|
|
}
|
|
|
|
static grib_section* sub_section(grib_accessor* a)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static int notify_change(grib_accessor* self, grib_accessor* observed)
|
|
{
|
|
/* Default behaviour is to notify creator */
|
|
return grib_action_notify_change(self->creator, self, observed);
|
|
}
|
|
|
|
static void update_size(grib_accessor* a, size_t s)
|
|
{
|
|
grib_context_log(a->context, GRIB_LOG_FATAL,
|
|
"Accessor %s [%s] must implement 'update_size'", a->name, a->cclass->name);
|
|
}
|
|
|
|
static grib_accessor* next(grib_accessor* a, int mod)
|
|
{
|
|
grib_accessor* next = NULL;
|
|
if (a->next) {
|
|
next = a->next;
|
|
}
|
|
else {
|
|
if (a->parent->owner)
|
|
next = a->parent->owner->cclass->next(a->parent->owner, 0);
|
|
}
|
|
return next;
|
|
}
|
|
|
|
static int compare(grib_accessor* a, grib_accessor* b)
|
|
{
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* Redefined in all padding */
|
|
|
|
static size_t preferred_size(grib_accessor* a, int from_handle)
|
|
{
|
|
return a->length;
|
|
}
|
|
|
|
static int is_missing(grib_accessor* a)
|
|
{
|
|
int i = 0;
|
|
int is_missing = 1;
|
|
unsigned char ones = 0xff;
|
|
unsigned char* v = NULL;
|
|
|
|
if (a->flags & GRIB_ACCESSOR_FLAG_TRANSIENT) {
|
|
if (a->vvalue == NULL) {
|
|
grib_context_log(a->context, GRIB_LOG_ERROR, "%s internal error (flags=0x%lX)", a->name, a->flags);
|
|
Assert(!"grib_accessor_class_gen::is_missing(): a->vvalue == NULL");
|
|
return 0;
|
|
}
|
|
return a->vvalue->missing;
|
|
}
|
|
Assert(a->length >= 0);
|
|
|
|
v = grib_handle_of_accessor(a)->buffer->data + a->offset;
|
|
|
|
for (i = 0; i < a->length; i++) {
|
|
if (*v != ones) {
|
|
is_missing = 0;
|
|
break;
|
|
}
|
|
v++;
|
|
}
|
|
|
|
return is_missing;
|
|
}
|
|
|
|
static int unpack_double_element(grib_accessor* a, size_t i, double* val)
|
|
{
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int unpack_double_element_set(grib_accessor* a, const size_t* index_array, size_t len, double* val_array)
|
|
{
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int unpack_double_subarray(grib_accessor* a, double* val, size_t start, size_t len)
|
|
{
|
|
return GRIB_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static grib_accessor* make_clone(grib_accessor* a, grib_section* s, int* err)
|
|
{
|
|
*err = GRIB_NOT_IMPLEMENTED;
|
|
return NULL;
|
|
}
|