mirror of https://github.com/ecmwf/eccodes.git
829 lines
22 KiB
C
829 lines
22 KiB
C
/*
|
|
* Copyright 2005-2015 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.
|
|
*/
|
|
|
|
/*
|
|
*
|
|
* Description: routines for grib indexing form a set of files
|
|
*
|
|
*/
|
|
#include "grib_api_internal.h"
|
|
#define GRIB_START_ARRAY_SIZE 5000
|
|
#define GRIB_ARRAY_INCREMENT 1000
|
|
|
|
#define SWAP(a,b) temp=(a);(a)=(b);(b)=temp;
|
|
|
|
#define GRIB_ORDER_BY_ASC 1
|
|
#define GRIB_ORDER_BY_DESC -1
|
|
|
|
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;
|
|
}
|
|
|
|
static grib_fieldset* grib_fieldset_create_from_keys(grib_context* c,char** keys,int nkeys,int* err);
|
|
static grib_fieldset* grib_fieldset_create_from_order_by(grib_context* c,grib_order_by* ob,
|
|
int* err);
|
|
static int grib_fieldset_resize(grib_fieldset* set,size_t newsize);
|
|
static void grib_trim(char** x);
|
|
static grib_order_by* grib_fieldset_new_order_by(grib_context* c,char* z);
|
|
static int grib_fieldset_compare(grib_fieldset* set,int* i,int* j);
|
|
static void grib_fieldset_sort(grib_fieldset* set, int beg, int theEnd);
|
|
static int grib_fieldset_columns_resize(grib_fieldset* set,size_t newsize);
|
|
static grib_int_array* grib_fieldset_create_int_array(grib_context* c,size_t size);
|
|
static int grib_fieldset_resize_int_array(grib_int_array* a,size_t newsize);
|
|
static void grib_fieldset_delete_int_array(grib_int_array* f);
|
|
static void grib_fieldset_delete_columns(grib_fieldset* set);
|
|
static grib_field** grib_fieldset_create_fields(grib_context* c,size_t size);
|
|
static void grib_fieldset_delete_fields(grib_fieldset* set);
|
|
static int grib_fieldset_resize_fields(grib_fieldset* set,size_t newsize);
|
|
static int grib_fieldset_set_order_by(grib_fieldset* set,grib_order_by* ob);
|
|
|
|
|
|
/* --------------- grib_column functions ------------------*/
|
|
int grib_fieldset_new_column(grib_fieldset* set,int id,char* key,int type) {
|
|
grib_column* column=0;
|
|
grib_context* c;
|
|
int err=0;
|
|
|
|
if (!set) return GRIB_INVALID_ARGUMENT;
|
|
|
|
c=set->context;
|
|
|
|
set->columns[id].errors=(int*)grib_context_malloc_clear(c,
|
|
sizeof(int)*GRIB_START_ARRAY_SIZE);
|
|
|
|
switch (type) {
|
|
case GRIB_TYPE_LONG:
|
|
set->columns[id].long_values=(long*)grib_context_malloc_clear(c,
|
|
sizeof(long)*GRIB_START_ARRAY_SIZE);
|
|
if (!set->columns[id].long_values) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_new_column : Cannot malloc %d bytes",
|
|
sizeof(long)*GRIB_START_ARRAY_SIZE);
|
|
err=GRIB_OUT_OF_MEMORY;
|
|
return err;
|
|
}
|
|
break;
|
|
case GRIB_TYPE_DOUBLE:
|
|
set->columns[id].double_values=(double*)grib_context_malloc_clear(c,
|
|
sizeof(double)*GRIB_START_ARRAY_SIZE);
|
|
if (!set->columns[id].double_values) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_new_column : Cannot malloc %d bytes",
|
|
sizeof(double)*GRIB_START_ARRAY_SIZE);
|
|
err=GRIB_OUT_OF_MEMORY;
|
|
return err;
|
|
}
|
|
break;
|
|
case GRIB_TYPE_STRING:
|
|
set->columns[id].string_values=(char**)grib_context_malloc_clear(c,
|
|
sizeof(char*)*GRIB_START_ARRAY_SIZE);
|
|
if (!set->columns[id].string_values) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_new_column : Cannot malloc %d bytes",
|
|
sizeof(char*)*GRIB_START_ARRAY_SIZE);
|
|
err=GRIB_OUT_OF_MEMORY;
|
|
return err;
|
|
}
|
|
break;
|
|
default:
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_new_column : unknown column type %d",type);
|
|
grib_context_free(c,column);
|
|
return err;
|
|
}
|
|
|
|
set->columns[id].context=c;
|
|
set->columns[id].name=grib_context_strdup(c,key);
|
|
set->columns[id].type=type;
|
|
set->columns[id].values_array_size=GRIB_START_ARRAY_SIZE;
|
|
set->columns[id].size=0;
|
|
return err;
|
|
}
|
|
|
|
static void grib_fieldset_delete_columns(grib_fieldset* set) {
|
|
int i=0;
|
|
grib_context* c;
|
|
|
|
if (!set) return;
|
|
c=set->context;
|
|
|
|
for (i=0;i<set->columns_size;i++) {
|
|
int j=0;
|
|
switch (set->columns[i].type) {
|
|
case GRIB_TYPE_LONG:
|
|
grib_context_free(c,set->columns[i].long_values);
|
|
break;
|
|
case GRIB_TYPE_DOUBLE:
|
|
grib_context_free(c,set->columns[i].double_values);
|
|
break;
|
|
case GRIB_TYPE_STRING:
|
|
for (j=0;j<set->columns[i].size;j++)
|
|
grib_context_free(c,set->columns[i].string_values[j]);
|
|
break;
|
|
default:
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_new_column : unknown column type %d",set->columns[i].type);
|
|
}
|
|
grib_context_free(c,set->columns[i].errors);
|
|
grib_context_free(c,set->columns[i].name);
|
|
}
|
|
grib_context_free(c,set->columns);
|
|
}
|
|
|
|
static int grib_fieldset_columns_resize(grib_fieldset* set,size_t newsize) {
|
|
double* newdoubles;
|
|
long* newlongs;
|
|
char** newstrings;
|
|
int* newerrors;
|
|
int i=0;
|
|
grib_context* c;
|
|
|
|
if (!set || !set->columns) return GRIB_INVALID_ARGUMENT;
|
|
|
|
c=set->context;
|
|
|
|
if (newsize <= set->columns[0].values_array_size) return 0;
|
|
|
|
for (i=0;i<set->columns_size;i++) {
|
|
|
|
switch (set->columns[i].type) {
|
|
case GRIB_TYPE_LONG:
|
|
newlongs=(long*)grib_context_realloc(c,set->columns[i].long_values,
|
|
newsize*sizeof(long));
|
|
if (!newlongs ) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_columns_resize : Cannot malloc %d bytes",newsize-set->columns[i].values_array_size);
|
|
return GRIB_OUT_OF_MEMORY;
|
|
} else set->columns[i].long_values=newlongs;
|
|
break;
|
|
case GRIB_TYPE_DOUBLE:
|
|
newdoubles=(double*)grib_context_realloc(c,set->columns[i].double_values,
|
|
newsize*sizeof(double));
|
|
if (!newdoubles) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_columns_resize : Cannot malloc %d bytes",newsize-set->columns[i].values_array_size);
|
|
return GRIB_OUT_OF_MEMORY;
|
|
} else set->columns[i].double_values=newdoubles;
|
|
break;
|
|
case GRIB_TYPE_STRING:
|
|
newstrings=(char**)grib_context_realloc(c,set->columns[i].string_values,
|
|
newsize*sizeof(char*));
|
|
if (!newstrings) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_columns_resize : Cannot malloc %d bytes",newsize-set->columns[i].values_array_size);
|
|
return GRIB_OUT_OF_MEMORY;
|
|
} else set->columns[i].string_values=newstrings;
|
|
break;
|
|
}
|
|
newerrors=(int*)grib_context_realloc(c,set->columns[i].errors,newsize*sizeof(int));
|
|
if (!newerrors) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_columns_resize : Cannot malloc %d bytes",
|
|
set->columns[i].errors,newsize*sizeof(int));
|
|
return GRIB_OUT_OF_MEMORY;
|
|
} else set->columns[i].errors=newerrors;
|
|
|
|
set->columns[i].values_array_size=newsize;
|
|
|
|
}
|
|
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
int grib_fieldset_column_copy_from_handle(grib_handle* h,grib_fieldset* set,int i) {
|
|
int err=0;
|
|
long lval=0;
|
|
double dval=0;
|
|
char sval[1024];
|
|
size_t slen=1024;
|
|
if (!set || !h || set->columns[i].type == 0)
|
|
return GRIB_INVALID_ARGUMENT;
|
|
|
|
if (set->columns[i].size >= set->columns[i].values_array_size)
|
|
grib_fieldset_columns_resize(set,set->columns[i].values_array_size+GRIB_ARRAY_INCREMENT);
|
|
|
|
switch (set->columns[i].type) {
|
|
case GRIB_TYPE_LONG:
|
|
err=grib_get_long(h,set->columns[i].name,&lval);
|
|
set->columns[i].long_values[set->columns[i].size]=lval;
|
|
break;
|
|
case GRIB_TYPE_DOUBLE:
|
|
err=grib_get_double(h,set->columns[i].name,&dval);
|
|
set->columns[i].double_values[set->columns[i].size]=dval;
|
|
break;
|
|
case GRIB_TYPE_STRING:
|
|
err=grib_get_string(h,set->columns[i].name,sval,&slen);
|
|
set->columns[i].string_values[set->columns[i].size]=grib_context_strdup(h->context,sval);
|
|
break;
|
|
}
|
|
|
|
set->columns[i].errors[set->columns[i].size]=err;
|
|
set->columns[i].size++;
|
|
|
|
return err;
|
|
}
|
|
|
|
/* --------------- grib_fieldset functions ------------------*/
|
|
grib_fieldset* grib_fieldset_new_from_files(grib_context* c,char* filenames[],
|
|
int nfiles, char** keys,int nkeys,
|
|
char* where_string,char* order_by_string,int* err) {
|
|
int i=0;
|
|
int ret=GRIB_SUCCESS;
|
|
grib_order_by* ob=NULL;
|
|
|
|
grib_fieldset* set=0;
|
|
|
|
if (!c) c=grib_context_get_default( );
|
|
|
|
if (( (!keys || nkeys==0) && !order_by_string )
|
|
|| !filenames ) {
|
|
*err=GRIB_INVALID_ARGUMENT;
|
|
return NULL;
|
|
}
|
|
|
|
if (order_by_string) {
|
|
ob=grib_fieldset_new_order_by(c,order_by_string);
|
|
if (!ob) {
|
|
*err=GRIB_INVALID_ORDERBY;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if ( !keys || nkeys==0 ) {
|
|
set=grib_fieldset_create_from_order_by(c,ob,err);
|
|
} else {
|
|
set=grib_fieldset_create_from_keys(c,keys,nkeys,err);
|
|
}
|
|
|
|
*err=GRIB_SUCCESS;
|
|
for (i=0;i<nfiles;i++) {
|
|
ret=grib_fieldset_add(set,filenames[i]);
|
|
if (ret != GRIB_SUCCESS) {
|
|
*err=ret;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (where_string) grib_fieldset_apply_where(set,where_string);
|
|
|
|
if (order_by_string) {
|
|
if (!set->order_by && ob) *err=grib_fieldset_set_order_by(set,ob);
|
|
if (*err!=GRIB_SUCCESS) return NULL;
|
|
grib_fieldset_sort(set,0,set->size-1);
|
|
grib_fieldset_rewind(set);
|
|
}
|
|
|
|
return set;
|
|
}
|
|
|
|
static grib_fieldset* grib_fieldset_create_from_keys(grib_context* c,char** keys,int nkeys,
|
|
int* err) {
|
|
grib_fieldset* set=0;
|
|
size_t msize=0,size=0;
|
|
int i=0;
|
|
int type=0;
|
|
int default_type=GRIB_TYPE_STRING;
|
|
|
|
if (!c) c=grib_context_get_default( );
|
|
|
|
size=GRIB_START_ARRAY_SIZE;
|
|
|
|
msize=sizeof(grib_fieldset);
|
|
set=(grib_fieldset*)grib_context_malloc_clear(c,msize);
|
|
if (!set) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_create : Cannot malloc %d bytes",msize);
|
|
return NULL;
|
|
}
|
|
|
|
set->context=c;
|
|
set->fields_array_size=size;
|
|
set->size=0;
|
|
set->current=-1;
|
|
set->fields=0;
|
|
set->filter=0;
|
|
set->order=0;
|
|
set->columns=0;
|
|
set->where=0;
|
|
set->order_by=0;
|
|
|
|
set->fields=grib_fieldset_create_fields(set->context,size);
|
|
|
|
set->order=grib_fieldset_create_int_array(c,size);
|
|
set->filter=grib_fieldset_create_int_array(c,size);
|
|
for (i=0;i<set->filter->size;i++)
|
|
set->filter->el[i]=i;
|
|
|
|
set->columns=(grib_column*)grib_context_malloc_clear(c,sizeof(grib_column)*nkeys);
|
|
if (!set->columns) {
|
|
grib_context_log(c,GRIB_LOG_ERROR,"grib_fieldset_new_query: memory allocation error");
|
|
*err=GRIB_OUT_OF_MEMORY;
|
|
return NULL;
|
|
}
|
|
for (i=0;i<nkeys;i++) {
|
|
char* key=grib_context_strdup(c,keys[i]);
|
|
char* p=key;
|
|
while(*p != ':' && *p != '\0') p++;
|
|
if (*p==':') {
|
|
type = grib_type_to_int(*(p+1));
|
|
*p='\0';
|
|
} else {
|
|
type = default_type;
|
|
}
|
|
*err=grib_fieldset_new_column(set,i,key,type);
|
|
grib_context_free(c,key);
|
|
}
|
|
|
|
set->columns_size=nkeys;
|
|
|
|
return set;
|
|
|
|
}
|
|
|
|
static grib_fieldset* grib_fieldset_create_from_order_by(grib_context* c,grib_order_by* ob,
|
|
int* err) {
|
|
char** keys=NULL;
|
|
size_t nkeys=0;
|
|
int i=0;
|
|
grib_fieldset* set=NULL;
|
|
grib_order_by* next=ob;
|
|
|
|
while(next) {nkeys++;next=next->next;}
|
|
|
|
keys=(char**)grib_context_malloc_clear( c,nkeys*sizeof(char*));
|
|
|
|
next=ob;
|
|
i=0;
|
|
while(next) {keys[i++]=next->key;next=next->next;}
|
|
|
|
set=grib_fieldset_create_from_keys(c,keys,nkeys,err);
|
|
grib_context_free(c,keys);
|
|
|
|
return set;
|
|
}
|
|
|
|
int grib_fieldset_apply_where(grib_fieldset* set,const char* where_string) {
|
|
int err=GRIB_NOT_IMPLEMENTED;
|
|
grib_math* m=0;
|
|
|
|
if (!set) return GRIB_INVALID_ARGUMENT;
|
|
|
|
m=grib_math_new(set->context,where_string,&err);
|
|
|
|
print_math(m);
|
|
printf("\n");
|
|
return err;
|
|
}
|
|
|
|
int grib_fieldset_apply_order_by(grib_fieldset* set,const char* order_by_string) {
|
|
int err=0;
|
|
grib_order_by* ob=NULL;
|
|
|
|
if (!set) return GRIB_INVALID_ARGUMENT;
|
|
|
|
if (set->order_by) {
|
|
grib_fieldset_delete_order_by(set->context,set->order_by);
|
|
set->order_by=0;
|
|
}
|
|
|
|
ob=grib_fieldset_new_order_by(set->context,(char*)order_by_string);
|
|
if ((err=grib_fieldset_set_order_by(set,ob)) != GRIB_SUCCESS)
|
|
return err;
|
|
|
|
if (set->order_by) grib_fieldset_sort(set,0,set->size-1);
|
|
|
|
grib_fieldset_rewind(set);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
static int grib_fieldset_compare(grib_fieldset* set,int* i,int* j) {
|
|
int ret=0;
|
|
double d=0;
|
|
int idkey=0;
|
|
grib_order_by* ob=0;
|
|
int ii=0,jj=0;
|
|
int *order=0,*filter=0;
|
|
|
|
if (!set || !set->order_by) return GRIB_INVALID_ARGUMENT;
|
|
ob=set->order_by;
|
|
order=set->order->el;
|
|
filter=set->filter->el;
|
|
|
|
ii=*(set->filter->el+*(order+*i));
|
|
jj=*(set->filter->el+*(order+*j));
|
|
|
|
while (ob) {
|
|
idkey=ob->idkey;
|
|
switch (set->columns[idkey].type) {
|
|
case GRIB_TYPE_STRING:
|
|
ret=strcmp(set->columns[idkey].string_values[ii],
|
|
set->columns[idkey].string_values[jj]);
|
|
break;
|
|
|
|
case GRIB_TYPE_DOUBLE:
|
|
d=set->columns[idkey].double_values[ii]-
|
|
set->columns[idkey].double_values[jj];
|
|
if (d > 0 ) ret=1;
|
|
else if ( d == 0) ret=0;
|
|
else ret=-1;
|
|
break;
|
|
|
|
case GRIB_TYPE_LONG:
|
|
ret=set->columns[idkey].long_values[ii]-
|
|
set->columns[idkey].long_values[jj];
|
|
break;
|
|
default:
|
|
return GRIB_INVALID_TYPE;
|
|
}
|
|
if (ret!=0) {
|
|
ret*=ob->mode;
|
|
break;
|
|
}
|
|
ob=ob->next;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void grib_fieldset_sort(grib_fieldset* set, int beg, int theEnd) {
|
|
double temp;
|
|
int l=0,r=0;
|
|
if (theEnd > beg) {
|
|
l = beg + 1;
|
|
r = theEnd;
|
|
while (l < r) {
|
|
if ( grib_fieldset_compare(set,&l,&beg) <= 0 ) {
|
|
l++;
|
|
} else if(grib_fieldset_compare(set,&r,&beg) >= 0 ) {
|
|
r--;
|
|
} else {
|
|
SWAP(set->order->el[l],set->order->el[r])
|
|
}
|
|
}
|
|
|
|
if (grib_fieldset_compare(set,&l,&beg) < 0) {
|
|
SWAP(set->order->el[l],set->order->el[beg])
|
|
l--;
|
|
} else {
|
|
l--;
|
|
SWAP(set->order->el[l],set->order->el[beg])
|
|
}
|
|
|
|
grib_fieldset_sort(set, beg, l);
|
|
grib_fieldset_sort(set, r, theEnd);
|
|
}
|
|
}
|
|
|
|
void grib_fieldset_delete_order_by(grib_context* c,grib_order_by* order_by) {
|
|
grib_order_by* ob=order_by;
|
|
|
|
if (!c) c=grib_context_get_default();
|
|
|
|
while (order_by) {
|
|
if (order_by->key) free(order_by->key);
|
|
ob=order_by;
|
|
order_by=order_by->next;
|
|
grib_context_free( c,ob);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
static grib_order_by* grib_fieldset_new_order_by(grib_context* c,char* obstr) {
|
|
char *t1=0,*t2=0,*p=0;
|
|
int id=0;
|
|
char *z=0,*zs=0;
|
|
int mode,mode_default=GRIB_ORDER_BY_ASC;
|
|
grib_order_by *ob,*sob;
|
|
|
|
if (!obstr) return NULL;
|
|
|
|
z=grib_context_strdup(c,obstr);
|
|
zs=z;
|
|
grib_trim(&z);
|
|
|
|
if (strlen(z)==0) {return 0;}
|
|
|
|
ob=(grib_order_by*)grib_context_malloc_clear(c,sizeof(grib_order_by));
|
|
sob=ob;
|
|
ob->key=0;
|
|
ob->idkey=0;
|
|
ob->mode=0;
|
|
ob->next=0;
|
|
|
|
if (z) t1=strtok(z,",");
|
|
|
|
while (t1) {
|
|
grib_trim(&t1);
|
|
t2=grib_context_strdup(c,t1);
|
|
p=t2;
|
|
while ( *p != ' ' && *p != '\0' ) p++;
|
|
mode=mode_default;
|
|
if (p != t2) {
|
|
while ( *p == ' ' && *p != '\0' ) p++;
|
|
if (*p != '\0') {
|
|
*(p-1)='\0';
|
|
if (!grib_inline_strcmp(p,"asc")) mode=GRIB_ORDER_BY_ASC;
|
|
if (!grib_inline_strcmp(p,"desc")) mode=GRIB_ORDER_BY_DESC;
|
|
}
|
|
grib_trim(&p);
|
|
}
|
|
grib_trim(&t2);
|
|
id=-1;
|
|
t1=strtok(NULL,",");
|
|
|
|
if (ob->key) {
|
|
ob->next=(grib_order_by*)grib_context_malloc_clear(c,sizeof(grib_order_by));
|
|
ob=ob->next;
|
|
ob->key=0;
|
|
ob->next=0;
|
|
}
|
|
ob->mode=mode;
|
|
ob->key=t2;
|
|
ob->idkey=id;
|
|
}
|
|
|
|
if (z) grib_context_free(c,z);
|
|
return sob;
|
|
}
|
|
|
|
|
|
void grib_fieldset_delete(grib_fieldset* set) {
|
|
grib_context* c=0;
|
|
if (!set) return;
|
|
|
|
c=set->context;
|
|
|
|
grib_fieldset_delete_columns(set);
|
|
|
|
grib_fieldset_delete_fields(set);
|
|
grib_fieldset_delete_int_array(set->order);
|
|
grib_fieldset_delete_int_array(set->filter);
|
|
|
|
grib_context_free( c, set);
|
|
}
|
|
|
|
|
|
int grib_fieldset_add(grib_fieldset* set,char* filename) {
|
|
int ret=GRIB_SUCCESS;
|
|
int err=0;
|
|
int i=0;
|
|
grib_handle* h=0;
|
|
int nkeys;
|
|
grib_file* file;
|
|
double offset=0;
|
|
long length=0;
|
|
grib_context* c=0;
|
|
|
|
if (!set || !filename ) return GRIB_INVALID_ARGUMENT;
|
|
c=set->context;
|
|
|
|
nkeys=set->columns_size;
|
|
|
|
file=grib_file_open(filename,"r",&err);
|
|
if (!file || !file->handle) return err;
|
|
|
|
while((h = grib_handle_new_from_file(c,file->handle,&ret))
|
|
!= NULL || ret != GRIB_SUCCESS ) {
|
|
if (!h) return ret;
|
|
|
|
err=GRIB_SUCCESS;
|
|
for (i=0;i<set->columns_size;i++) {
|
|
err=grib_fieldset_column_copy_from_handle(h,set,i);
|
|
if (err != GRIB_SUCCESS) ret=err;
|
|
}
|
|
if (err==GRIB_SUCCESS || err==GRIB_NOT_FOUND) {
|
|
if (set->fields_array_size < set->columns[0].values_array_size) {
|
|
ret=grib_fieldset_resize(set,set->columns[0].values_array_size);
|
|
if (ret!=GRIB_SUCCESS) return ret;
|
|
}
|
|
offset=0;
|
|
ret=grib_get_double(h,"offset",&offset);
|
|
set->fields[set->size]=(grib_field*)grib_context_malloc_clear(c,sizeof(grib_field));
|
|
set->fields[set->size]->file=file;
|
|
file->refcount++;
|
|
set->fields[set->size]->offset=(off_t)offset;
|
|
ret=grib_get_long(h,"totalLength",&length);
|
|
set->fields[set->size]->length=length;
|
|
set->filter->el[set->size]=set->size;
|
|
set->order->el[set->size]=set->size;
|
|
set->size=set->columns[0].size;
|
|
}
|
|
grib_handle_delete(h);
|
|
}
|
|
if (h) grib_handle_delete(h);
|
|
|
|
grib_file_close(file->name,&err);
|
|
|
|
grib_fieldset_rewind(set);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int grib_fieldset_resize(grib_fieldset* set,size_t newsize) {
|
|
int err=0;
|
|
|
|
err=grib_fieldset_resize_fields(set,newsize);
|
|
if (err != 0) return err;
|
|
grib_fieldset_resize_int_array(set->order,newsize);
|
|
if (err != 0) return err;
|
|
grib_fieldset_resize_int_array(set->filter,newsize);
|
|
if (err != 0) return err;
|
|
|
|
set->fields_array_size=newsize;
|
|
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
void grib_fieldset_rewind(grib_fieldset* set) {
|
|
if (set) set->current=0;
|
|
}
|
|
|
|
grib_handle* grib_fieldset_next_handle(grib_fieldset* set,int* err) {
|
|
grib_handle* h;
|
|
*err=GRIB_SUCCESS;
|
|
h=grib_fieldset_retrieve(set,set->current,err);
|
|
if (*err==GRIB_SUCCESS) {
|
|
set->current++;
|
|
}
|
|
return h;
|
|
}
|
|
|
|
int grib_fieldset_count(grib_fieldset* set) {
|
|
return set->size;
|
|
}
|
|
|
|
grib_handle* grib_fieldset_retrieve(grib_fieldset* set,int i,int* err) {
|
|
grib_handle* h=0;
|
|
grib_field* field=0;
|
|
*err=GRIB_SUCCESS;
|
|
if ( !set ) {
|
|
*err=GRIB_INVALID_ARGUMENT;
|
|
return NULL;
|
|
}
|
|
if (i >= set->size) return NULL;
|
|
|
|
field=set->fields[set->filter->el[set->order->el[i]]];
|
|
grib_file_open(field->file->name,"r",err);
|
|
if (*err!=GRIB_SUCCESS) return NULL;
|
|
|
|
fseeko(field->file->handle,field->offset,SEEK_SET);
|
|
h=grib_handle_new_from_file(set->context,field->file->handle,err);
|
|
if (*err!=GRIB_SUCCESS) return NULL;
|
|
|
|
grib_file_close(field->file->name,err);
|
|
|
|
return h;
|
|
}
|
|
|
|
static grib_int_array* grib_fieldset_create_int_array(grib_context* c,size_t size) {
|
|
grib_int_array* a;
|
|
int i=0;
|
|
|
|
if (!c) c=grib_context_get_default();
|
|
|
|
a=(grib_int_array*)grib_context_malloc_clear(c,sizeof(grib_int_array));
|
|
|
|
if (!a) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_create_int_array : Cannot malloc %d bytes",
|
|
sizeof(grib_int_array));
|
|
return NULL;
|
|
}
|
|
|
|
a->el=(int*)grib_context_malloc_clear(c,sizeof(int)*size);
|
|
if (!a->el) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_fieldset_create_int_array : Cannot malloc %d bytes",
|
|
sizeof(int)*size);
|
|
return NULL;
|
|
}
|
|
|
|
a->size=size;
|
|
a->context=c;
|
|
for (i=0;i<size;i++) a->el[i]=i;
|
|
|
|
return a;
|
|
}
|
|
|
|
static int grib_fieldset_resize_int_array(grib_int_array* a,size_t newsize) {
|
|
int* el;
|
|
int err=0;
|
|
if (!a) return GRIB_INVALID_ARGUMENT;
|
|
|
|
newsize=newsize*sizeof(int);
|
|
|
|
el=(int*)grib_context_realloc(a->context,a->el,newsize);
|
|
if (!el) {
|
|
grib_context_log(a->context, GRIB_LOG_ERROR,
|
|
"grib_fieldset_resize_int_array : Cannot malloc %d bytes",
|
|
newsize);
|
|
return GRIB_OUT_OF_MEMORY;
|
|
} else a->el=el;
|
|
a->size=newsize;
|
|
return err;
|
|
}
|
|
|
|
static void grib_fieldset_delete_int_array(grib_int_array* f)
|
|
{
|
|
grib_context* c = NULL;
|
|
|
|
if (!f) return;
|
|
c = f->context;
|
|
|
|
grib_context_free(c,f->el);
|
|
grib_context_free(c,f);
|
|
|
|
}
|
|
|
|
static grib_field** grib_fieldset_create_fields(grib_context* c,size_t size) {
|
|
int i;
|
|
grib_field** fields=(grib_field**)grib_context_malloc_clear(c,size*sizeof(grib_field*));
|
|
if (!fields) return NULL;
|
|
for (i=0;i<size;i++) fields[i]=0;
|
|
return fields;
|
|
}
|
|
|
|
static int grib_fieldset_resize_fields(grib_fieldset* set,size_t newsize) {
|
|
int err=0;
|
|
int i;
|
|
grib_field** fields;
|
|
if (!set) return GRIB_INVALID_ARGUMENT;
|
|
|
|
fields=(grib_field**)grib_context_realloc(set->context,set->fields,newsize*sizeof(grib_field*));
|
|
if (!fields) {
|
|
grib_context_log(set->context, GRIB_LOG_ERROR,
|
|
"grib_fieldset_resize_fields : Cannot malloc %d bytes",
|
|
newsize*sizeof(grib_field*));
|
|
return GRIB_OUT_OF_MEMORY;
|
|
} else set->fields=fields;
|
|
|
|
for (i=set->fields_array_size;i<newsize;i++)
|
|
set->fields[i]=0;
|
|
|
|
set->fields_array_size=newsize;
|
|
return err;
|
|
}
|
|
|
|
static void grib_fieldset_delete_fields(grib_fieldset* set) {
|
|
int i;
|
|
for (i=0;i<set->size;i++) {
|
|
if (!set->fields[i]) continue;
|
|
set->fields[i]->file->refcount--;
|
|
grib_context_free(set->context,set->fields[i]);
|
|
}
|
|
grib_context_free(set->context,set->fields);
|
|
}
|
|
|
|
static void grib_trim(char** x) {
|
|
char* p=0;
|
|
while (**x == ' ' && **x != '\0' ) (*x)++;
|
|
if (**x == '\0') return;
|
|
p=(*x)+strlen(*x)-1;
|
|
while ( *p == ' ' ) {*p='\0';p--;}
|
|
if ( *p == ' ' ) *p='\0';
|
|
}
|
|
|
|
static int grib_fieldset_set_order_by(grib_fieldset* set,grib_order_by* ob) {
|
|
grib_order_by* next=ob;
|
|
char* p=NULL;
|
|
int i=0;
|
|
|
|
while(next) {
|
|
next->idkey=-1;
|
|
p=next->key;
|
|
while (*p!= 0 && *p != ':') p++;
|
|
if (*p ==':') *p=0;
|
|
for (i=0;i<set->columns_size; i++) {
|
|
if (!grib_inline_strcmp(next->key,set->columns[i].name)) {
|
|
next->idkey=i;
|
|
break;
|
|
}
|
|
}
|
|
if (next->idkey == -1) {
|
|
grib_context_log(set->context,GRIB_LOG_ERROR,
|
|
"Unable to apply the order by. Key missing from the fieldset.\n");
|
|
return GRIB_MISSING_KEY;
|
|
}
|
|
next=next->next;
|
|
}
|
|
|
|
set->order_by=ob;
|
|
|
|
return GRIB_SUCCESS;
|
|
|
|
}
|
|
|