eccodes/src/grib_value.c

1767 lines
51 KiB
C

/*
* Copyright 2005-2017 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 *
***************************************************************************/
#include "grib_api_internal.h"
GRIB_INLINE static int grib_inline_strcmp(const char* a,const char* b)
{
if (*a != *b) return 1;
while((*a!=0 && *b!=0) && *(a) == *(b) ) {a++;b++;}
return (*a==0 && *b==0) ? 0 : 1;
}
int grib_set_expression(grib_handle* h, const char* name,grib_expression* e)
{
grib_accessor* a = grib_find_accessor(h, name);
int ret = GRIB_SUCCESS;
if(a){
if(a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
return GRIB_READ_ONLY;
ret = grib_pack_expression(a, e);
if(ret == GRIB_SUCCESS){
return grib_dependency_notify_change(a);
}
return ret;
}
return GRIB_NOT_FOUND;
}
int grib_set_expression_internal(grib_handle* h, const char* name,grib_expression* e)
{
grib_accessor* a = grib_find_accessor(h, name);
int ret = GRIB_SUCCESS;
if(a){
ret = grib_pack_expression(a, e);
if(ret == GRIB_SUCCESS){
return grib_dependency_notify_change(a);
}
return ret;
}
return GRIB_NOT_FOUND;
}
int grib_set_long_internal(grib_handle* h, const char* name, long val)
{
grib_context* c=h->context;
int ret = GRIB_SUCCESS;
grib_accessor* a =NULL;
size_t l = 1;
a = grib_find_accessor(h, name);
if (h->context->debug)
printf("ECCODES DEBUG grib_set_long_internal %s=%ld\n",name,(long)val);
if(a){
ret = grib_pack_long(a, &val, &l);
if(ret == GRIB_SUCCESS){
return grib_dependency_notify_change(a);
}
grib_context_log(c,GRIB_LOG_ERROR,"unable to set %s=%ld as long (%s)",
name,val,grib_get_error_message(ret));
return ret;
}
grib_context_log(c,GRIB_LOG_ERROR,"unable to find accessor %s",name);
return GRIB_NOT_FOUND;
}
int grib_set_long(grib_handle* h, const char* name, long val)
{
int ret = GRIB_SUCCESS;
grib_accessor* a =NULL;
size_t l = 1;
a = grib_find_accessor(h, name);
if (h->context->debug)
printf("ECCODES DEBUG grib_set_long %s=%ld\n",name,(long)val);
if(a){
if(a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
return GRIB_READ_ONLY;
ret = grib_pack_long(a, &val, &l);
if(ret == GRIB_SUCCESS)
return grib_dependency_notify_change(a);
return ret;
}
return GRIB_NOT_FOUND;
}
int grib_set_double_internal(grib_handle* h, const char* name, double val)
{
int ret = GRIB_SUCCESS;
grib_accessor* a =NULL;
size_t l = 1;
a = grib_find_accessor(h, name);
if (h->context->debug)
printf("ECCODES DEBUG grib_set_double_internal %s=%g\n",name,val);
if(a){
ret = grib_pack_double(a, &val, &l);
if(ret == GRIB_SUCCESS){
return grib_dependency_notify_change(a);
}
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to set %s=%g as double (%s)",
name,val,grib_get_error_message(ret));
return ret;
}
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to find accessor %s",name);
return GRIB_NOT_FOUND;
}
typedef struct grib_key_err grib_key_err;
struct grib_key_err {
char* name;
int err;
grib_key_err* next;
};
int grib_copy_namespace(grib_handle* dest, const char* name, grib_handle* src)
{
int *err=NULL;
int type, error_code=0;
size_t len;
char *sval = NULL;
unsigned char *uval = NULL;
double *dval = NULL;
long *lval = NULL;
grib_key_err* key_err=NULL;
grib_key_err* first=NULL;
int todo=1,count=0;
grib_keys_iterator* iter=NULL;
if (!dest || !src) return GRIB_NULL_HANDLE;
iter=grib_keys_iterator_new(src,0,name);
if (!iter) {
grib_context_log(src->context,GRIB_LOG_ERROR,"grib_copy_namespace: unable to get iterator for %s",name );
return GRIB_INTERNAL_ERROR;
}
while(grib_keys_iterator_next(iter)) {
grib_key_err* k=(grib_key_err*)grib_context_malloc_clear(src->context,sizeof(grib_key_err));
k->err=GRIB_NOT_FOUND;
k->name=grib_context_strdup(src->context,grib_keys_iterator_get_name(iter));
if (key_err==NULL) {
key_err=k;
first=k;
} else {
key_err->next=k;
key_err=key_err->next;
}
}
count=0;
todo=1;
while (todo && count<4) {
grib_accessor* a=NULL;
key_err=first;
while(key_err) {
char* key=key_err->name;
err=&(key_err->err);
if (*err==GRIB_SUCCESS) {
key_err=key_err->next;
continue;
}
if ((a=grib_find_accessor(dest,key))==NULL) {
key_err->err=GRIB_NOT_FOUND;
key_err=key_err->next;
continue;
}
if (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) {
key_err->err=GRIB_SUCCESS;
key_err=key_err->next;
continue;
}
if ( grib_is_missing(src,key,err) && *err == 0 && (*err=grib_set_missing(dest,key))) {
if ( *err!=GRIB_SUCCESS && *err!=GRIB_NOT_FOUND) return *err;
key_err=key_err->next;
continue;
}
if ((*err=grib_get_native_type(dest,key,&type))!=GRIB_SUCCESS) {
if ( *err!=GRIB_SUCCESS && *err!=GRIB_NOT_FOUND) return *err;
key_err=key_err->next;
continue;
}
if((*err = grib_get_size(src,key,&len)) != GRIB_SUCCESS) return *err;
switch (type) {
case GRIB_TYPE_STRING:
len=512;
sval = (char*)grib_context_malloc(src->context,len*sizeof(char));
if((*err = grib_get_string(src,key,sval,&len)) != GRIB_SUCCESS)
return *err;
if((*err = grib_set_string(dest,key,sval,&len)) != GRIB_SUCCESS)
return *err;
grib_context_free(src->context,sval);
break;
case GRIB_TYPE_LONG:
lval = (long*)grib_context_malloc(src->context,len*sizeof(long));
if((*err = grib_get_long_array(src,key,lval,&len)) != GRIB_SUCCESS)
return *err;
if((*err = grib_set_long_array(dest,key,lval,len)) != GRIB_SUCCESS)
return *err;
grib_context_free(src->context,lval);
break;
case GRIB_TYPE_DOUBLE:
dval = (double*)grib_context_malloc(src->context,len*sizeof(double));
if((*err = grib_get_double_array(src,key,dval,&len)) != GRIB_SUCCESS)
return *err;
if((*err = grib_set_double_array(dest,key,dval,len)) != GRIB_SUCCESS)
return *err;
grib_context_free(src->context,dval);
break;
case GRIB_TYPE_BYTES:
if (len==0) len=512;
uval = (unsigned char *)grib_context_malloc(src->context,len*sizeof(unsigned char));
if((*err = grib_get_bytes(src,key,uval,&len)) != GRIB_SUCCESS)
return *err;
if((*err = grib_get_bytes(dest,key,uval,&len)) != GRIB_SUCCESS)
return *err;
grib_context_free(src->context,uval);
break;
default:
break;
}
key_err=key_err->next;
}
count++;
key_err=first;
todo=0;
while(key_err) {
if (key_err->err==GRIB_NOT_FOUND) {
todo=1;
break;
}
key_err=key_err->next;
}
}
error_code = *err; /* copy the error code before cleanup */
grib_keys_iterator_delete(iter);
key_err=first;
while (key_err) {
grib_key_err* next=key_err->next;
grib_context_free(src->context,key_err->name);
grib_context_free(src->context,key_err);
key_err=next;
}
return error_code;
}
int grib_set_double(grib_handle* h, const char* name, double val)
{
int ret = GRIB_SUCCESS;
grib_accessor* a =NULL;
size_t l = 1;
a = grib_find_accessor(h, name);
if (h->context->debug)
printf("ECCODES DEBUG grib_set_double %s=%g\n",name,val);
if(a){
if(a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
return GRIB_READ_ONLY;
ret = grib_pack_double(a, &val, &l);
if(ret == GRIB_SUCCESS)
return grib_dependency_notify_change(a);
return ret;
}
return GRIB_NOT_FOUND;
}
int grib_set_string_internal(grib_handle* h, const char* name,
const char* val, size_t *length)
{
int ret = GRIB_SUCCESS;
grib_accessor* a =NULL;
a = grib_find_accessor(h, name);
if (h->context->debug)
printf("ECCODES DEBUG grib_set_string_internal %s=%s\n",name,val);
if(a){
ret = grib_pack_string(a, val, length);
if(ret == GRIB_SUCCESS){
return grib_dependency_notify_change(a);
}
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to set %s=%s as string (%s)",
name,val,grib_get_error_message(ret));
return ret;
}
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to find accessor %s",name);
return GRIB_NOT_FOUND;
}
int grib_set_string(grib_handle* h, const char* name, const char* val, size_t *length)
{
int ret=0;
grib_accessor* a = NULL;
/* Second order doesn't have a proper representation for constant fields.
So best not to do the change of packing type.
Use strncmp to catch all flavours of second order packing e.g. grid_second_order_boustrophedonic
*/
if (!grib_inline_strcmp(name,"packingType") && !strncmp(val,"grid_second_order", 17)) {
long bitsPerValue=0;
size_t numCodedVals = 0;
grib_get_long(h,"bitsPerValue",&bitsPerValue);
if (bitsPerValue==0) {
if (h->context->debug) {
printf("ECCODES DEBUG grib_set_string packingType: Constant field cannot be encoded in second order. Packing not changed\n");
}
return 0;
}
/* GRIB-883: check if there are enough coded values */
ret = grib_get_size(h, "codedValues", &numCodedVals);
if (ret == GRIB_SUCCESS && numCodedVals < 3) {
if (h->context->debug) {
printf("ECCODES DEBUG grib_set_string packingType: not enough coded values for second order. Packing not changed\n");
}
return 0;
}
}
a = grib_find_accessor(h, name);
if (h->context->debug)
printf("ECCODES DEBUG grib_set_string %s=|%s|\n",name,val);
if(a)
{
if(a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
return GRIB_READ_ONLY;
ret=grib_pack_string(a, val, length);
if(ret == GRIB_SUCCESS){
return grib_dependency_notify_change(a);
}
return ret;
}
return GRIB_NOT_FOUND;
}
int grib_set_string_array(grib_handle* h, const char* name, const char** val, size_t length)
{
int ret=0;
grib_accessor* a;
a = grib_find_accessor(h, name);
if (h->context->debug) {
printf("ECCODES DEBUG grib_set_string_array key=%s %ld values\n",name,(long)length);
}
if(a)
{
if(a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
return GRIB_READ_ONLY;
ret=grib_pack_string_array(a, val, &length);
if(ret == GRIB_SUCCESS){
return grib_dependency_notify_change(a);
}
return ret;
}
return GRIB_NOT_FOUND;
}
int grib_set_bytes_internal(grib_handle* h, const char* name, const unsigned char* val, size_t *length)
{
int ret = GRIB_SUCCESS;
grib_accessor* a =NULL;
a = grib_find_accessor(h, name);
if(a){
ret = grib_pack_bytes(a, val, length);
if(ret == GRIB_SUCCESS){
return grib_dependency_notify_change(a);
}
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to set %s=%ld as bytes (%s)",
name,val,grib_get_error_message(ret));
return ret;
}
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to find accessor %s",name);
return GRIB_NOT_FOUND;
}
int grib_set_bytes(grib_handle* h, const char* name, const unsigned char* val, size_t *length)
{
int ret=0;
grib_accessor* a = grib_find_accessor(h, name);
if(a)
{
/* if(a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) */
/* return GRIB_READ_ONLY; */
ret=grib_pack_bytes(a, val, length);
if(ret == GRIB_SUCCESS){
return grib_dependency_notify_change(a);
}
return ret;
}
return GRIB_NOT_FOUND;
}
int grib_clear(grib_handle* h, const char* name)
{
int ret=0;
grib_accessor* a =NULL;
a = grib_find_accessor(h, name);
if(a) {
if (a->length ==0) return 0;
if ((ret=grib_pack_zero(a)) != GRIB_SUCCESS)
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to clear %s (%s)",
name,grib_get_error_message(ret));
return ret;
}
/*grib_context_log(h->context,GRIB_LOG_ERROR,"unable to find accessor %s",name);*/
return GRIB_NOT_FOUND;
}
int grib_set_missing_internal(grib_handle* h, const char* name)
{
int ret=0;
grib_accessor* a =NULL;
a = grib_find_accessor(h, name);
if(a) {
if(a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) {
ret=grib_pack_missing(a);
if(ret == GRIB_SUCCESS)
return grib_dependency_notify_change(a);
} else
ret=GRIB_VALUE_CANNOT_BE_MISSING;
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to set %s=missing (%s)",
name,grib_get_error_message(ret));
return ret;
}
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to find accessor %s",name);
return GRIB_NOT_FOUND;
}
int grib_set_missing(grib_handle* h, const char* name)
{
int ret=0;
grib_accessor* a =NULL;
a = grib_find_accessor(h, name);
if(a) {
if(a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
return GRIB_READ_ONLY;
if(a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) {
if (h->context->debug) printf("ECCODES DEBUG grib_set_missing %s\n",name);
ret=grib_pack_missing(a);
if(ret == GRIB_SUCCESS)
return grib_dependency_notify_change(a);
} else ret=GRIB_VALUE_CANNOT_BE_MISSING;
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to set %s=missing (%s)",
name,grib_get_error_message(ret));
return ret;
}
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to find accessor %s",name);
return GRIB_NOT_FOUND;
}
int grib_is_missing_long(grib_accessor* a,long x)
{
int ret = ( a==NULL || (a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING)) && (x==GRIB_MISSING_LONG) ? 1 : 0;
return ret;
}
int grib_is_missing_double(grib_accessor* a,double x)
{
int ret = ( a==NULL || (a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING)) && (x==GRIB_MISSING_DOUBLE) ? 1 : 0;
return ret;
}
int grib_is_missing_string(grib_accessor* a, unsigned char* x, size_t len)
{
/* For a string value to be missing, every character has to be */
/* all 1's (i.e. 0xFF) */
int ret;
size_t i=0;
if (len==0) return 0;
ret=1;
for (i=0;i<len;i++) {
if (x[i] != 0xFF ) {
ret=0;
break;
}
}
ret = ( a==NULL || ( (a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) && ret==1 )) ? 1 : 0;
return ret;
}
int grib_accessor_is_missing(grib_accessor* a,int* err)
{
*err=GRIB_SUCCESS;
if(a)
{
if(a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING)
return grib_is_missing_internal(a);
else
return 0;
}
else
{
*err=GRIB_NOT_FOUND;
return 1;
}
}
int grib_is_missing(grib_handle* h, const char* name,int* err)
{
grib_accessor* a = grib_find_accessor(h, name);
return grib_accessor_is_missing(a,err);
}
/* Return true if the given key exists (is defined) in our grib message */
int grib_is_defined(grib_handle* h, const char* name)
{
grib_accessor* a = grib_find_accessor(h, name);
return (a ? 1 : 0);
}
int grib_set_flag(grib_handle *h,const char* name,unsigned long flag)
{
grib_accessor* a=grib_find_accessor(h,name);
if (!a) return GRIB_NOT_FOUND;
a->flags|=flag;
return GRIB_SUCCESS;
}
static int _grib_set_double_array_internal(grib_handle* h,grib_accessor* a,
const double* val, size_t buffer_len,size_t *encoded_length,int check)
{
if(a) {
int err = _grib_set_double_array_internal(h,a->same,val,buffer_len,encoded_length,check);
if(check && (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY))
return GRIB_READ_ONLY;
if(err == GRIB_SUCCESS)
{
size_t len = buffer_len - *encoded_length;
if(len) {
err = grib_pack_double(a, val + *encoded_length, &len);
*encoded_length += len;
if(err == GRIB_SUCCESS){
return grib_dependency_notify_change(a);
}
}
else {
grib_get_size(h,a->name,encoded_length);
err = GRIB_WRONG_ARRAY_SIZE;
}
}
return err;
}
else {
return GRIB_SUCCESS;
}
}
static int _grib_set_double_array(grib_handle* h, const char* name,
const double* val, size_t length,int check)
{
size_t encoded = 0;
grib_accessor* a = grib_find_accessor(h, name);
int err=0;
if (!a) return GRIB_NOT_FOUND ;
if (name[0]=='/' || name[0]=='#' ) {
if(check && (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY))
return GRIB_READ_ONLY;
err=grib_pack_double(a, val, &length);
encoded=length;
} else err=_grib_set_double_array_internal(h,a,val,length,&encoded,check);
if(err == GRIB_SUCCESS && length > encoded)
err = GRIB_ARRAY_TOO_SMALL;
if(err == GRIB_SUCCESS)
return grib_dependency_notify_change(a);
return err;
}
int grib_set_double_array_internal(grib_handle* h, const char* name, const double* val, size_t length)
{
int ret=0;
if (h->context->debug)
printf("ECCODES DEBUG grib_set_double_array_internal key=%s %ld values\n",name,(long)length);
if (length==0) {
grib_accessor* a = grib_find_accessor(h, name);
ret=grib_pack_double(a, val , &length);
} else {
ret=_grib_set_double_array(h,name,val,length,0);
}
if (ret!=GRIB_SUCCESS)
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to set double array %s (%s)",
name,grib_get_error_message(ret));
/*if (h->context->debug) printf("ECCODES DEBUG grib_set_double_array_internal key=%s --DONE\n",name);*/
return ret;
}
static int __grib_set_double_array(grib_handle* h, const char* name, const double* val, size_t length, int check)
{
double v=val[0];
int constant,i;
if (h->context->debug)
printf("ECCODES DEBUG grib_set_double_array key=%s %ld values\n",name,(long)length);
if (length==0) {
grib_accessor* a = grib_find_accessor(h, name);
return grib_pack_double(a, val , &length);
}
/*second order doesn't have a proper representation for constant fields
the best is not to do the change of packing type if the field is constant
*/
if (!strcmp(name,"values") || !strcmp(name,"codedValues")) {
double missingValue;
int ret=0;
ret=grib_get_double(h,"missingValue",&missingValue);
if (ret) missingValue=9999;
v=missingValue;
constant=1;
for (i=0;i<length;i++) {
if (val[i]!=missingValue) {
if (v==missingValue) {
v=val[i];
} else if (v!=val[i]) {
constant=0;
break;
}
}
}
if (constant) {
char packingType[50]={0,};
size_t slen=50;
grib_get_string(h,"packingType",packingType,&slen);
if (!strcmp(packingType,"grid_second_order") ||
!strcmp(packingType,"grid_second_order_no_SPD") ||
!strcmp(packingType,"grid_second_order_SPD1") ||
!strcmp(packingType,"grid_second_order_SPD2") ||
!strcmp(packingType,"grid_second_order_SPD3")
) {
ret = 0;
slen=11; /*length of 'grid_simple' */
if (h->context->debug) {
printf("ECCODES DEBUG __grib_set_double_array: Cannot use second order packing for constant fields. Using simple packing\n");
}
ret = grib_set_string(h,"packingType","grid_simple",&slen);
if (ret != GRIB_SUCCESS) {
if (h->context->debug) {
printf("ECCODES DEBUG __grib_set_double_array: could not switch to simple packing!\n");
}
}
}
}
}
return _grib_set_double_array(h,name,val,length,check);
}
int grib_set_force_double_array(grib_handle* h, const char* name, const double* val, size_t length)
{
/* GRIB-285: Same as grib_set_double_array but allows setting of READ-ONLY keys like codedValues */
/* Use with great caution!! */
return __grib_set_double_array(h, name, val, length, /*check=*/0);
}
int grib_set_double_array(grib_handle* h, const char* name, const double* val, size_t length)
{
return __grib_set_double_array(h, name, val, length, /*check=*/1);
}
static int _grib_set_long_array_internal(grib_handle* h,grib_accessor* a,const long* val, size_t buffer_len,size_t *encoded_length,int check)
{
if(a) {
int err = _grib_set_long_array_internal(h,a->same,val,buffer_len,encoded_length,check);
if(check && (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY))
return GRIB_READ_ONLY;
if(err == GRIB_SUCCESS)
{
size_t len = buffer_len - *encoded_length;
if(len) {
err = grib_pack_long(a, val + *encoded_length, &len);
*encoded_length += len;
}
else {
grib_get_size(h,a->name,encoded_length);
err = GRIB_WRONG_ARRAY_SIZE;
}
}
return err;
}
else {
return GRIB_SUCCESS;
}
}
static int _grib_set_long_array(grib_handle* h, const char* name, const long* val, size_t length,int check)
{
size_t encoded = 0;
grib_accessor* a = grib_find_accessor(h, name);
int err =0;
if (!a) return GRIB_NOT_FOUND ;
if (name[0]=='/' || name[0]=='#' ) {
if(check && (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY))
return GRIB_READ_ONLY;
err=grib_pack_long(a, val, &length);
encoded=length;
} else err=_grib_set_long_array_internal(h,a,val,length,&encoded,check);
if(err == GRIB_SUCCESS && length > encoded)
err = GRIB_ARRAY_TOO_SMALL;
if(err == GRIB_SUCCESS)
return grib_dependency_notify_change(a);
return err;
}
int grib_set_long_array_internal(grib_handle* h, const char* name, const long* val, size_t length)
{
int ret=_grib_set_long_array(h,name,val,length,0);
if (ret!=GRIB_SUCCESS)
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to set long array %s (%s)",
name,grib_get_error_message(ret));
return ret;
}
int grib_set_long_array(grib_handle* h, const char* name, const long* val, size_t length)
{
return _grib_set_long_array(h,name,val,length,1);
}
int grib_get_long_internal(grib_handle* h, const char* name, long* val)
{
int ret = grib_get_long(h,name,val);
if(ret!=GRIB_SUCCESS) {
grib_context_log(h->context,GRIB_LOG_ERROR,
"unable to get %s as long (%s)",
name, grib_get_error_message(ret));
}
return ret;
}
int grib_is_in_dump(grib_handle* h, const char* name)
{
grib_accessor* a=grib_find_accessor(h, name);
if (a!=NULL && (a->flags & GRIB_ACCESSOR_FLAG_DUMP))
return 1;
else
return 0;
}
int grib_attributes_count(grib_accessor* a, size_t* size)
{
if (a) {
*size=0;
while (a->attributes[*size]!=NULL) {(*size)++;}
return GRIB_SUCCESS;
}
return GRIB_NOT_FOUND;
}
int grib_get_long(grib_handle* h, const char* name, long* val)
{
size_t length = 1;
grib_accessor* a = NULL;
grib_accessors_list* al=NULL;
int ret=0;
if (name[0] == '/' ) {
al=grib_find_accessors_list(h,name);
if (!al) return GRIB_NOT_FOUND;
ret=grib_unpack_long(al->accessor, val , &length);
grib_context_free(h->context,al);
} else {
a=grib_find_accessor(h, name);
if(!a) return GRIB_NOT_FOUND;
ret=grib_unpack_long(a, val , &length);
}
return ret;
}
int grib_get_double_internal(grib_handle* h, const char* name, double* val)
{
int ret = grib_get_double(h,name,val);
if(ret!=GRIB_SUCCESS)
grib_context_log(h->context,GRIB_LOG_ERROR,
"unable to get %s as double (%s)",
name, grib_get_error_message(ret));
return ret;
}
int grib_get_double(grib_handle* h, const char* name, double* val)
{
size_t length = 1;
grib_accessor* a = NULL;
grib_accessors_list* al=NULL;
int ret=0;
if (name[0] == '/' ) {
al=grib_find_accessors_list(h,name);
if (!al) return GRIB_NOT_FOUND;
ret=grib_unpack_double(al->accessor, val , &length);
grib_context_free(h->context,al);
} else {
a=grib_find_accessor(h, name);
if(!a) return GRIB_NOT_FOUND;
ret=grib_unpack_double(a, val , &length);
}
return ret;
}
int grib_get_double_element_internal(grib_handle* h, const char* name, int i,double* val)
{
int ret = grib_get_double_element(h,name,i,val);
if(ret!=GRIB_SUCCESS)
grib_context_log(h->context,GRIB_LOG_ERROR,
"unable to get %s as double element (%s)",
name, grib_get_error_message(ret));
return ret;
}
int grib_get_double_element(grib_handle* h, const char* name, int i, double* val)
{
grib_accessor* act = grib_find_accessor(h, name);
if (act) {
return grib_unpack_double_element(act, i,val);
}
return GRIB_NOT_FOUND;
}
int grib_points_get_values(grib_handle* h, grib_points* points, double* val)
{
int i,ret;
grib_accessor* a=NULL;
a=grib_find_accessor(h,"values");
for (i=0;i<points->n_groups;i++) {
ret=grib_unpack_double_subarray(a,val,points->group_start[i],points->group_len[i]);
if (ret) return ret;
val+=points->group_len[i];
}
return GRIB_SUCCESS;
}
int grib_get_double_elements(grib_handle* h, const char* name, int* index_array, long len, double* val_array)
{
double* values=0;
int err=0;
size_t size=0, num_bytes = 0;
long j = 0;
grib_accessor* act =NULL;
act= grib_find_accessor(h, name);
if (!act) return GRIB_NOT_FOUND;
err=_grib_get_size(h,act,&size);
if (err!=GRIB_SUCCESS) {
grib_context_log(h->context,GRIB_LOG_ERROR,"grib_get_double_elements: cannot get size of %s\n",name);
return err;
}
/* Check index array has valid values */
for (j=0;j<len;j++) {
const int anIndex = index_array[j];
if (anIndex < 0 || anIndex >= size) {
grib_context_log(h->context,GRIB_LOG_ERROR,
"grib_get_double_elements: index out of range: %d (should be between 0 and %ld)", anIndex, size-1);
return GRIB_INVALID_ARGUMENT;
}
}
num_bytes = size * sizeof(double);
values=(double*)grib_context_malloc(h->context, num_bytes);
if (!values) {
grib_context_log(h->context,GRIB_LOG_ERROR,"grib_get_double_elements: unable to allocate %ld bytes\n", num_bytes);
return GRIB_OUT_OF_MEMORY;
}
err = grib_unpack_double(act, values, &size);
if (!err) {
for (j=0;j<len;j++) {
val_array[j] = values[index_array[j]];
}
}
grib_context_free(h->context,values);
return err;
}
int grib_get_string_internal(grib_handle* h, const char* name, char* val, size_t *length)
{
int ret = grib_get_string(h,name,val,length);
if(ret!=GRIB_SUCCESS)
grib_context_log(h->context,GRIB_LOG_ERROR,
"unable to get %s as string (%s)",
name, grib_get_error_message(ret));
return ret;
}
int grib_get_string(grib_handle* h, const char* name, char* val, size_t *length)
{
grib_accessor* a = NULL;
grib_accessors_list* al=NULL;
int ret=0;
if (name[0] == '/' ) {
al=grib_find_accessors_list(h,name);
if (!al) return GRIB_NOT_FOUND;
ret=grib_unpack_string(al->accessor, val, length);
grib_context_free(h->context,al);
return ret;
} else {
a=grib_find_accessor(h, name);
if(!a) return GRIB_NOT_FOUND;
return grib_unpack_string(a, val , length);
}
}
int grib_get_bytes_internal(grib_handle* h, const char* name, unsigned char* val, size_t *length)
{
int ret = grib_get_bytes(h,name,val,length);
if(ret!=GRIB_SUCCESS)
grib_context_log(h->context,GRIB_LOG_ERROR,
"unable to get %s as bytes (%s)",
name, grib_get_error_message(ret));
return ret;
}
int grib_get_bytes(grib_handle* h, const char* name, unsigned char* val, size_t *length)
{
int err=0;
grib_accessor* act = grib_find_accessor(h, name);
err = act? grib_unpack_bytes(act, val, length) : GRIB_NOT_FOUND;
if(err) grib_context_log(h->context,GRIB_LOG_ERROR,
"grib_get_bytes %s failed %s", name, grib_get_error_message(err));
return err;
}
int grib_get_native_type(grib_handle* h, const char* name,int* type)
{
grib_accessors_list* al=NULL;
grib_accessor* a =NULL;
*type = GRIB_TYPE_UNDEFINED;
DebugAssert( name != NULL && strlen(name) > 0 );
if (name[0] == '/' ) {
al=grib_find_accessors_list(h,name);
if (!al) return GRIB_NOT_FOUND;
*type = grib_accessor_get_native_type(al->accessor);
grib_context_free(h->context,al);
} else {
a=grib_find_accessor(h, name);
if(!a) return GRIB_NOT_FOUND;
*type = grib_accessor_get_native_type(a);
}
return GRIB_SUCCESS;
}
const char* grib_get_accessor_class_name(grib_handle* h, const char* name)
{
grib_accessor* act = grib_find_accessor(h, name);
return act?act->cclass->name:NULL;
}
int _grib_get_double_array_internal(grib_handle* h,grib_accessor* a,double* val, size_t buffer_len,size_t *decoded_length)
{
if(a) {
int err = _grib_get_double_array_internal(h,a->same,val,buffer_len,decoded_length);
if ( err == GRIB_SUCCESS )
{
size_t len = buffer_len - *decoded_length;
err = grib_unpack_double(a, val + *decoded_length, &len);
*decoded_length += len;
}
return err;
}
else {
return GRIB_SUCCESS;
}
}
int grib_get_double_array_internal(grib_handle* h, const char* name, double* val, size_t *length)
{
int ret = grib_get_double_array(h,name,val,length);
if(ret!=GRIB_SUCCESS)
grib_context_log(h->context,GRIB_LOG_ERROR,
"unable to get %s as double array (%s)",
name, grib_get_error_message(ret));
return ret;
}
int grib_get_double_array(grib_handle* h, const char* name, double* val, size_t *length)
{
size_t len = *length;
grib_accessor* a = NULL;
grib_accessors_list* al=NULL;
int ret=0;
if (name[0] == '/' ) {
al=grib_find_accessors_list(h,name);
if (!al) return GRIB_NOT_FOUND;
ret=grib_accessors_list_unpack_double(al,val,length);
grib_context_free(h->context,al);
return ret;
} else {
a=grib_find_accessor(h, name);
if(!a) return GRIB_NOT_FOUND;
if (name[0] == '#') {
return grib_unpack_double(a, val , length);
} else {
*length = 0;
return _grib_get_double_array_internal(h,a,val,len,length);
}
}
}
int _grib_get_string_length(grib_accessor* a, size_t* size)
{
size_t s=0;
*size = 0;
while(a) {
s = grib_string_length(a);
if (s > *size) *size=s;
a = a->same;
}
(*size)+=1;
return GRIB_SUCCESS;
}
int grib_get_string_length(grib_handle* h, const char* name,size_t* size)
{
grib_accessor* a = grib_find_accessor(h, name);
if(!a) return GRIB_NOT_FOUND;
return _grib_get_string_length(a,size);
}
int _grib_get_size(grib_handle* h, grib_accessor* a,size_t* size)
{
long count=0;
int err=0;
if(!a) return GRIB_NOT_FOUND;
*size = 0;
while(a) {
if (err==0)
{
err=grib_value_count(a,&count);
if (err) return err;
*size += count;
}
a = a->same;
}
return GRIB_SUCCESS;
}
int grib_get_size(grib_handle* h, const char* name,size_t* size)
{
grib_accessor* a =NULL;
grib_accessors_list* al=NULL;
int ret=0;
*size=0;
if (name[0] == '/') {
al=grib_find_accessors_list(h,name);
if (!al) return GRIB_NOT_FOUND;
ret=grib_accessors_list_value_count(al,size);
grib_context_free(h->context,al);
return ret;
} else {
a=grib_find_accessor(h, name);
if(!a) return GRIB_NOT_FOUND;
if (name[0]=='#') {
long count=*size;
ret=grib_value_count(a,&count);
*size=count;
return ret;
} else return _grib_get_size(h, a,size);
}
}
int grib_get_length(grib_handle* h, const char* name, size_t* length)
{
return grib_get_string_length(h, name, length);
}
int grib_get_count(grib_handle* h, const char* name,size_t* size)
{
grib_accessor* a = grib_find_accessor(h, name);
if(!a) return GRIB_NOT_FOUND;
*size = 0;
while(a) {
(*size)++;
a = a->same;
}
return GRIB_SUCCESS;
}
int grib_get_offset(grib_handle* h, const char* key,size_t* val)
{
grib_accessor* act = grib_find_accessor(h, key);
if(act) {
*val = (size_t)grib_byte_offset(act);
return GRIB_SUCCESS;
}
return GRIB_NOT_FOUND;
}
int _grib_get_string_array_internal(grib_handle* h,grib_accessor* a,char** val, size_t buffer_len,size_t *decoded_length)
{
if(a) {
int err = _grib_get_string_array_internal(h,a->same,val,buffer_len,decoded_length);
if(err == GRIB_SUCCESS)
{
size_t len = buffer_len - *decoded_length;
err = grib_unpack_string_array(a, val + *decoded_length, &len);
*decoded_length += len;
}
return err;
} else {
return GRIB_SUCCESS;
}
}
int grib_get_string_array(grib_handle* h, const char* name, char** val, size_t *length)
{
size_t len = *length;
grib_accessor* a = NULL;
grib_accessors_list* al=NULL;
int ret=0;
if (name[0] == '/' ) {
al=grib_find_accessors_list(h,name);
if (!al) return GRIB_NOT_FOUND;
ret=grib_accessors_list_unpack_string(al,val,length);
grib_context_free(h->context,al);
return ret;
} else {
a=grib_find_accessor(h, name);
if(!a) return GRIB_NOT_FOUND;
if (name[0]=='#') {
return grib_unpack_string_array(a, val , length);
} else {
*length = 0;
return _grib_get_string_array_internal(h,a,val,len,length);
}
}
}
int _grib_get_long_array_internal(grib_handle* h,grib_accessor* a,long* val, size_t buffer_len,size_t *decoded_length)
{
if(a) {
int err = _grib_get_long_array_internal(h,a->same,val,buffer_len,decoded_length);
if(err == GRIB_SUCCESS)
{
size_t len = buffer_len - *decoded_length;
err = grib_unpack_long(a, val + *decoded_length, &len);
*decoded_length += len;
}
return err;
} else {
return GRIB_SUCCESS;
}
}
int grib_get_long_array_internal(grib_handle* h, const char* name, long* val, size_t *length)
{
int ret = grib_get_long_array(h,name,val,length);
if(ret!=GRIB_SUCCESS)
grib_context_log(h->context,GRIB_LOG_ERROR,
"unable to get %s as long array (%s)",
name, grib_get_error_message(ret));
return ret;
}
int grib_get_long_array(grib_handle* h, const char* name, long* val, size_t *length)
{
size_t len = *length;
grib_accessor* a = NULL;
grib_accessors_list* al=NULL;
int ret=0;
if (name[0] == '/' ) {
al=grib_find_accessors_list(h,name);
if (!al) return GRIB_NOT_FOUND;
ret=grib_accessors_list_unpack_long(al,val,length);
grib_context_free(h->context,al);
return ret;
} else {
a=grib_find_accessor(h, name);
if(!a) return GRIB_NOT_FOUND;
if (name[0]=='#') {
return grib_unpack_long(a, val , length);
} else {
*length = 0;
return _grib_get_long_array_internal(h,a,val,len,length);
}
}
return ret;
}
static void grib_clean_key_value(grib_context* c,grib_key_value_list* kv)
{
if (kv->long_value) grib_context_free(c,kv->long_value);
kv->long_value=NULL;
if (kv->double_value) grib_context_free(c,kv->double_value);
kv->double_value=NULL;
if (kv->string_value) grib_context_free(c,kv->string_value);
kv->string_value=NULL;
if (kv->namespace_value) grib_key_value_list_delete(c,kv->namespace_value);
kv->namespace_value=NULL;
kv->error=0;
kv->has_value=0;
kv->size=0;
}
static int grib_get_key_value(grib_handle* h,grib_key_value_list* kv)
{
int err=0;
size_t size=0;
grib_keys_iterator* iter=NULL;
grib_key_value_list* list=NULL;
if (kv->has_value) grib_clean_key_value(h->context,kv);
err=grib_get_size(h,kv->name,&size);
if (err) {
kv->error=err;
return err;
}
if (size==0) size=512;
switch (kv->type) {
case GRIB_TYPE_LONG:
kv->long_value=(long*)grib_context_malloc_clear(h->context,size*sizeof(long));
err=grib_get_long_array(h,kv->name,kv->long_value,&size);
kv->error=err;
break;
case GRIB_TYPE_DOUBLE:
kv->double_value=(double*)grib_context_malloc_clear(h->context,size*sizeof(double));
err=grib_get_double_array(h,kv->name,kv->double_value,&size);
kv->error=err;
break;
case GRIB_TYPE_STRING:
grib_get_string_length(h,kv->name,&size);
kv->string_value=(char*)grib_context_malloc_clear(h->context,size*sizeof(char));
err=grib_get_string(h,kv->name,kv->string_value,&size);
kv->error=err;
break;
case GRIB_TYPE_BYTES:
kv->string_value=(char*)grib_context_malloc_clear(h->context,size*sizeof(char));
err=grib_get_bytes(h,kv->name,(unsigned char*)kv->string_value,&size);
kv->error=err;
break;
case GRIB_NAMESPACE:
iter=grib_keys_iterator_new(h,0,kv->name);
list=(grib_key_value_list*)grib_context_malloc_clear(h->context,sizeof(grib_key_value_list));
kv->namespace_value=list;
while(grib_keys_iterator_next(iter))
{
list->name=grib_keys_iterator_get_name(iter);
err=grib_get_native_type(h,list->name,&(list->type));
err=grib_get_key_value(h,list);
list->next=(grib_key_value_list*)grib_context_malloc_clear(h->context,sizeof(grib_key_value_list));
list=list->next;
}
grib_keys_iterator_delete(iter);
break;
default:
err=grib_get_native_type(h,kv->name,&(kv->type));
err=grib_get_key_value(h,kv);
break;
}
kv->has_value=1;
return err;
}
grib_key_value_list* grib_key_value_list_clone(grib_context* c,grib_key_value_list* list)
{
grib_key_value_list* next=list;
grib_key_value_list* the_clone=(grib_key_value_list*)grib_context_malloc_clear(c,sizeof(grib_key_value_list));
grib_key_value_list* p=the_clone;
while (next && next->name) {
p->name=grib_context_strdup(c,next->name);
p->type=next->type;
next=next->next;
}
return the_clone;
}
void grib_key_value_list_delete(grib_context* c,grib_key_value_list* kvl)
{
grib_key_value_list* next=kvl;
grib_key_value_list* p=NULL;
while (next) {
p=next->next;
if (next->type == GRIB_NAMESPACE)
grib_key_value_list_delete(c,next->namespace_value);
grib_clean_key_value(c,next);
grib_context_free(c,next);
next=p;
}
}
int grib_get_key_value_list(grib_handle* h,grib_key_value_list* list)
{
int ret=0;
grib_key_value_list* kvl=list;
while (kvl) {
ret=grib_get_key_value(h,kvl);
kvl=kvl->next;
}
return ret;
}
int grib_get_values(grib_handle* h,grib_values* args,size_t count)
{
int ret=0;
int i=0;
for (i=0; i<count; i++) {
char buff[1024]={0,};
size_t len=sizeof(buff)/sizeof(*buff);
if (!args[i].name) {args[i].error=GRIB_INVALID_ARGUMENT;continue;}
if ( args[i].type == 0 ) {
args[i].error=grib_get_native_type(h,args[i].name,&(args[i].type));
if (args[i].error != GRIB_SUCCESS) ret=args[i].error;
}
switch(args[i].type) {
case GRIB_TYPE_LONG:
args[i].error = grib_get_long(h,args[i].name,&(args[i].long_value));
if (args[i].error != GRIB_SUCCESS) ret=args[i].error;
break;
case GRIB_TYPE_DOUBLE:
args[i].error = grib_get_double(h,args[i].name,&(args[i].double_value));
if (args[i].error != GRIB_SUCCESS) ret=args[i].error;
break;
case GRIB_TYPE_STRING:
args[i].error = grib_get_string(h,args[i].name,buff,&len);
args[i].string_value=strdup(buff);
if (args[i].error != GRIB_SUCCESS) ret=args[i].error;
break;
default:
args[i].error = grib_get_string(h,args[i].name,buff,&len);
args[i].string_value=strdup(buff);
if (args[i].error != GRIB_SUCCESS) ret=args[i].error;
break;
}
}
return ret;
}
int grib_set_values(grib_handle* h,grib_values* args,size_t count)
{
int i, error=0;
int err=0;
size_t len;
int more = 1;
int stack = h->values_stack++;
Assert(h->values_stack < MAX_SET_VALUES - 1);
h->values[stack] = args;
h->values_count[stack] = count;
for(i = 0; i < count ; i++)
args[i].error = GRIB_NOT_FOUND;
while(more)
{
more = 0;
for(i = 0; i < count ; i++)
{
if(args[i].error != GRIB_NOT_FOUND)
continue;
switch(args[i].type)
{
case GRIB_TYPE_LONG:
error = grib_set_long(h,args[i].name,args[i].long_value);
args[i].error=error;
if(args[i].error == GRIB_SUCCESS) more = 1;
break;
case GRIB_TYPE_DOUBLE:
args[i].error = grib_set_double(h,args[i].name,args[i].double_value);
if(args[i].error == GRIB_SUCCESS) more = 1;
break;
case GRIB_TYPE_STRING:
len = strlen(args[i].string_value);
args[i].error = grib_set_string(h,args[i].name,args[i].string_value,&len);
if(args[i].error == GRIB_SUCCESS) more = 1;
break;
case GRIB_TYPE_MISSING:
args[i].error = grib_set_missing(h,args[i].name);
if(args[i].error == GRIB_SUCCESS) more = 1;
break;
default:
grib_context_log(h->context,GRIB_LOG_ERROR, "grib_set_values[%d] %s invalid type %d", i, args[i].name, args[i].type);
args[i].error = GRIB_INVALID_ARGUMENT;
break;
}
/*if (args[i].error != GRIB_SUCCESS)
grib_context_log(h->context,GRIB_LOG_ERROR,"unable to set %s (%s)",
args[i].name,grib_get_error_message(args[i].error)); */
}
}
h->values[stack] = NULL;
h->values_count[stack] = 0;
h->values_stack--;
for(i = 0; i < count ; i++) {
if(args[i].error != GRIB_SUCCESS)
{
grib_context_log(h->context,GRIB_LOG_ERROR,
"grib_set_values[%d] %s (%d) failed: %s", i, args[i].name, args[i].type,
grib_get_error_message(args[i].error));
err= err==GRIB_SUCCESS ? args[i].error : err;
}
}
return err;
}
int grib_get_nearest_smaller_value(grib_handle* h, const char* name,
double val,double* nearest)
{
grib_accessor* act = grib_find_accessor(h, name);
Assert(act);
return grib_nearest_smaller_value(act,val,nearest);
}
void grib_print_values(grib_values* values,int count)
{
int i;
for(i = 0; i < count ; i++)
{
printf("%s = ",values[i].name);
switch(values[i].type)
{
case GRIB_TYPE_LONG: printf("%ld",values[i].long_value); break;
case GRIB_TYPE_DOUBLE: printf("%g",values[i].double_value); break;
case GRIB_TYPE_STRING: printf("%s",values[i].string_value); break;
}
printf("\n");
}
}
int grib_values_check(grib_handle* h, grib_values* values, int count)
{
int i=0;
long long_value;
double double_value;
unsigned char ubuff[1024]={0,};
char buff[1024]={0,};
size_t len=1024;
for (i=0; i<count; i++) {
if ( values[i].type == 0 ) {
values[i].error=GRIB_INVALID_TYPE;
return values[i].error;
}
switch(values[i].type) {
case GRIB_TYPE_LONG:
values[i].error = grib_get_long(h,values[i].name,&long_value);
if (values[i].error != GRIB_SUCCESS) return values[i].error;
if (long_value != values[i].long_value) {
values[i].error=GRIB_VALUE_DIFFERENT;
return values[i].error;
}
break;
case GRIB_TYPE_DOUBLE:
values[i].error = grib_get_double(h,values[i].name,&double_value);
if (values[i].error != GRIB_SUCCESS) return values[i].error;
if (double_value != values[i].double_value) {
values[i].error=GRIB_VALUE_DIFFERENT;
return values[i].error;
}
break;
case GRIB_TYPE_STRING:
values[i].error = grib_get_string(h,values[i].name,buff,&len);
if (values[i].error != GRIB_SUCCESS) return values[i].error;
if (strcmp(values[i].string_value,buff)) {
values[i].error=GRIB_VALUE_DIFFERENT;
return values[i].error;
}
break;
case GRIB_TYPE_BYTES:
values[i].error = grib_get_bytes(h,values[i].name,ubuff,&len);
if (values[i].error != GRIB_SUCCESS) return values[i].error;
if (memcmp(values[i].string_value,ubuff,len)) {
values[i].error=GRIB_VALUE_DIFFERENT;
return values[i].error;
}
break;
default:
values[i].error=GRIB_INVALID_TYPE;
return values[i].error;
}
}
return 0;
}
int grib_key_equal(grib_handle* h1,grib_handle* h2,const char* key,int type,int *err)
{
double d1,d2;
long l1,l2;
char s1[500]={0,};
char s2[500]={0,};
size_t len1,len2;
if ( type != GRIB_TYPE_DOUBLE &&
type != GRIB_TYPE_LONG &&
type != GRIB_TYPE_STRING ) {
*err=grib_get_native_type(h1,key,&type);
}
switch (type) {
case GRIB_TYPE_DOUBLE:
*err=grib_get_double( h1,key,&d1);
*err=grib_get_double( h2,key,&d2);
if (d1 != d2) return 0;
break;
case GRIB_TYPE_LONG:
*err=grib_get_long( h1,key,&l1);
*err=grib_get_long( h2,key,&l2);
if (l1 != l2) return 0;
break;
default:
len1=sizeof(s1)/sizeof(*s1);
len2=sizeof(s2)/sizeof(*s2);
*err=grib_get_string( h1,key,s1,&len1);
*err=grib_get_string( h2,key,s2,&len2);
if (grib_inline_strcmp(s1,s2)) return 0;
break;
}
return 1;
}
int codes_copy_key(grib_handle* h1,grib_handle* h2,const char* key,int type)
{
double d;
double* ad;
long l;
long* al;
char* s=0;
char** as=0;
size_t len1,len;
int err=0;
if ( type != GRIB_TYPE_DOUBLE &&
type != GRIB_TYPE_LONG &&
type != GRIB_TYPE_STRING ) {
err=grib_get_native_type(h1,key,&type);
if (err) return err;
}
err=grib_get_size(h1,key,&len1);
if (err) return err;
switch (type) {
case GRIB_TYPE_DOUBLE:
if (len1==1) {
err=grib_get_double(h1,key,&d);
if (err) return err;
grib_context_log(h1->context,GRIB_LOG_DEBUG,"codes_copy_key: %s=%g\n",key,d);
err=grib_set_double(h2,key,d);
return err;
} else {
ad=(double*)grib_context_malloc_clear(h1->context,len1*sizeof(double));
err=grib_get_double_array(h1,key,ad,&len1);
if (err) return err;
err=grib_set_double_array(h2,key,ad,len1);
grib_context_free(h1->context,ad);
return err;
}
break;
case GRIB_TYPE_LONG:
if (len1==1) {
err=grib_get_long(h1,key,&l);
if (err) return err;
grib_context_log(h1->context,GRIB_LOG_DEBUG,"codes_copy_key: %s=%ld\n",key,l);
err=grib_set_long(h2,key,l);
return err;
} else {
al=(long*)grib_context_malloc_clear(h1->context,len1*sizeof(long));
err=grib_get_long_array(h1,key,al,&len1);
if (err) return err;
err=grib_set_long_array(h2,key,al,len1);
grib_context_free(h1->context,al);
return err;
}
break;
case GRIB_TYPE_STRING:
err=grib_get_string_length(h1,key,&len);
if (len1==1) {
s=(char*)grib_context_malloc_clear(h1->context,len);
err=grib_get_string(h1,key,s,&len);
if (err) return err;
grib_context_log(h1->context,GRIB_LOG_DEBUG,"codes_copy_key: %s=%s\n",key,s);
err=grib_set_string(h2,key,s,&len);
grib_context_free(h1->context,s);
return err;
} else {
as=(char**)grib_context_malloc_clear(h1->context,len1*sizeof(char*));
err=grib_get_string_array(h1,key,as,&len1);
if (err) return err;
err=grib_set_string_array(h2,key,(const char **)as,len1);
return err;
}
break;
default:
return GRIB_INVALID_TYPE;
}
}