eccodes/src/grib_concept_index.c

169 lines
4.5 KiB
C

/*
* Copyright 2005-2018 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: concept index
*
*/
#include "grib_api_internal.h"
static grib_concept_index_entry* index_entry_new(grib_context* c,grib_concept_index_keys* keys) {
grib_concept_index_entry* entry=NULL;
Assert(keys);
if (!c) c=grib_context_get_default();
entry=grib_context_malloc_clear(c,sizeof(grib_concept_index_entry));
if (!entry)
grib_context_log(c,GRIB_LOG_FATAL,"grib_concept_index_entry unable to allocate");
e=entry;
while (keys && keys->name) {
e->name=grib_context_strdup(c,keys->name);
e->type=keys->type;
e->next=grib_context_malloc_clear(c,sizeof(grib_concept_index_entry));
if (!e->next)
grib_context_log(c,GRIB_LOG_FATAL,"grib_concept_index_entry unable to allocate");
e=e->next;
keys=keys->next;
}
return entry;
}
static void index_entry_delete(grib_context* c,grib_concept_index_entry* entry) {
grib_concept_index_entry* e;
while (entry) {
e=entry;
entry=entry->next;
grib_context_free(c,e->name);
grib_context_free(c,e->value);
grib_context_free(c,e);
}
}
static int index_insert_entry(grib_concept_index* index,grib_concept_index_entry* entry,void* object) {
int err=0;
int found=0;
grib_conditions_tree* cur=index->conditions;
grib_conditions_tree* prev=index->conditions;
grib_concept_index_keys* keys=index->keys;
while (keys->name) {
if (!cur) {
cur=grib_context_malloc_clear_persistent(index->context,sizeof(grib_conditions_tree));
if (!cur)
grib_context_log(index->context,GRIB_LOG_FATAL,"index_insert_entry unable to allocate");
prev->next=cur;
}
value = entry->value ? entry->value : "*";
while (cur && (!cur->value || (found=!strcmp(cur->value,value))==0) ) cur=cur->next;
if (!found) {
cur->next=grib_context_malloc_clear_persistent(index->context,sizeof(grib_conditions_tree));
if (!cur->next)
grib_context_log(index->context,GRIB_LOG_FATAL,"index_insert_entry unable to allocate");
cur=cur->next;
}
cur->value=grib_context_strdup(index->context,value);
entry=entry->next;
keys=keys->next;
prev=cur;
cur=cur->next_key;
}
while (cur) {
prev=cur;
cur=cur->next_key;
}
prev->object=object;
return err;
}
static void index_add_conditions(grib_concept_index* index,grib_concept_condition* condition) {
grib_concept_condition* c=condition;
char s[512]={0,};
grib_concept_index_entry* e;;
grib_concept_index_entry* entry=index_entry_new(index->context,index->keys);;
while (c) {
size_t size=512;
int type;
e=entry;
type = grib_expression_native_type(0,c->expression);
switch(type)
{
case GRIB_TYPE_LONG:
grib_expression_evaluate_long(0,c->expression,&lres);
sprintf(s,"%ld",lres);
break;
case GRIB_TYPE_DOUBLE:
grib_expression_evaluate_double(0,c->expression,&dres);
sprintf(s,"%g",dres);
break;
case GRIB_TYPE_STRING:
grib_expression_evaluate_string(0,c->expression,s,&size,&err);
break;
default:
Assert(0);
break;
}
while (e->name && strcmp(e->name,c->name))
e=e->next;
e->type=type;
e->value=grib_context_strdup(index->context,s);
if (!e->name) {
e->name=grib_context_strdup(index->context,c->name);
e->next=grib_context_malloc_clear_persistent(index->context,sizeof(grib_concept_index_entry));
if (!e->next)
grib_context_log(index->context,GRIB_LOG_FATAL,"index_add_conditions unable to allocate");
}
c=c->next;
}
index_insert_entry(index,entry,condition->name);
index_entry_delete(index->context,entry);
}
grib_concept_index* grib_concept_index_new_from_concept(grib_context* c,grib_concept_value* concept,int *err) {
grib_concept_index* index;
if (!c) c=grib_context_get_default();
index=grib_context_malloc_clear_persistent(c,sizeof(grib_concept_index));
index->keys=grib_context_malloc_clear_persistent(c,sizeof(grib_concept_index_key));
index->conditions=grib_context_malloc_clear_persistent(c,sizeof(grib_conditions_tree));
index->conditions=grib_context_malloc_clear_persistent(c,sizeof(grib_conditions_tree));
index->context=c;
while (concept) {
index_add_conditions(index,concept->conditions,err);
concept=concept->next;
}
return index;
}