eccodes/src/grib_accessor_class.c

383 lines
11 KiB
C
Raw Normal View History

2013-03-25 12:04:10 +00:00
/*
2015-01-05 15:45:46 +00:00
* Copyright 2005-2015 ECMWF.
2013-03-25 12:04:10 +00:00
*
* 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 "grib_accessor_classes_hash.c"
/* grib level */
/* This file is generated my ./make_class.pl */
#include "grib_accessor_class.h"
#if GRIB_PTHREADS
static pthread_once_t once = PTHREAD_ONCE_INIT;
static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
static void init() {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex1,&attr);
pthread_mutexattr_destroy(&attr);
}
#endif
struct table_entry
{
2013-06-19 12:13:45 +00:00
char *type;
grib_accessor_class **cclass;
2013-03-25 12:04:10 +00:00
};
static GRIB_INLINE int grib_inline_strcmp(const char* a,const char* b) {
2013-06-19 12:13:45 +00:00
if (*a != *b) return 1;
while((*a!=0 && *b!=0) && *(a) == *(b) ) {a++;b++;}
return (*a==0 && *b==0) ? 0 : 1;
2013-03-25 12:04:10 +00:00
}
static struct table_entry table[] =
{
2013-06-19 12:13:45 +00:00
/* This file is generated my ./make_class.pl */
2013-03-25 12:04:10 +00:00
#include "grib_accessor_factory.h"
};
#define NUMBER(x) (sizeof(x)/sizeof(x[0]))
grib_section* grib_create_root_section(const grib_context *context, grib_handle *h)
{
2013-06-19 12:13:45 +00:00
char* fpath=0;
grib_section* s = (grib_section*) grib_context_malloc_clear(context,sizeof(grib_section));
GRIB_PTHREAD_ONCE(&once,&init);
GRIB_MUTEX_LOCK(&mutex1);
if(h->context->grib_reader == NULL) {
if ((fpath=grib_context_full_defs_path(h->context,"boot.def"))==NULL) {
grib_context_log(h->context,GRIB_LOG_FATAL,
"Unable to find boot.def. Context path=%s", context->grib_definition_files_path);
}
grib_parse_file(h->context,fpath);
2013-03-25 12:04:10 +00:00
}
2013-06-19 12:13:45 +00:00
GRIB_MUTEX_UNLOCK(&mutex1);
s->h = h;
s->aclength = NULL;
s->owner = NULL;
s->block = (grib_block_of_accessors*)
grib_context_malloc_clear(context, sizeof(grib_block_of_accessors));
grib_context_log(context, GRIB_LOG_DEBUG, "Creating root section");
return s;
2013-03-25 12:04:10 +00:00
}
static GRIB_INLINE grib_accessor_class* get_class(grib_context* c,char* type) {
2013-06-19 12:13:45 +00:00
int i;
grib_accessor_class** the_class=NULL;
2013-06-19 12:13:45 +00:00
if ( (the_class=(grib_accessor_class**)grib_trie_get(c->classes,type))!=NULL)
return *(the_class);
2013-06-19 12:13:45 +00:00
for(i = 0; i < NUMBER(table) ; i++) {
if( grib_inline_strcmp(type,table[i].type) == 0 )
{
grib_trie_insert(c->classes,type,table[i].cclass);
return *(table[i].cclass);
}
}
grib_context_log(c,GRIB_LOG_FATAL,"unable to create class %s",type);
return NULL;
2013-03-25 12:04:10 +00:00
}
grib_accessor* grib_accessor_factory(grib_section* p, grib_action* creator,
2013-06-19 12:13:45 +00:00
const long len, grib_arguments* params)
2013-03-25 12:04:10 +00:00
{
2013-06-19 12:13:45 +00:00
grib_accessor_class* c=NULL;
grib_accessor* a=NULL;
size_t size=0;
c = get_class(p->h->context,creator->op);
/* c=*((grib_accessor_classes_hash(creator->op,strlen(creator->op)))->cclass); */
a = (grib_accessor*) grib_context_malloc_clear(p->h->context,c->size);
a->name = creator->name;
a->name_space = creator->name_space;
a->all_names[0] = creator->name;
a->all_name_spaces[0] = creator->name_space;
a->creator = creator;
a->next = NULL;
a->previous = NULL;
a->parent = p;
a->length = 0 ;
a->offset = 0;
a->flags = creator->flags;
a->set = creator->set;
if(p->block->last) {
a->offset = grib_get_next_position_offset(p->block->last);
#if 0
printf("offset: p->block->last %s %s %ld %ld\n",
p->block->last->cclass->name,
p->block->last->name,(long)p->block->last->offset,(long)p->block->last->length);
#endif
} else {
if(p->owner) {
a->offset = p->owner->offset;
} else
a->offset = 0;
}
a->cclass = c;
grib_init_accessor(a, len, params);
size = grib_get_next_position_offset(a);
if(size > p->h->buffer->ulength) {
if(!p->h->buffer->growable) {
if(!p->h->partial)
grib_context_log(p->h->context, GRIB_LOG_ERROR,
"Creating (%s)%s of %s at offset %d-%d over message boundary (%d)",
p->owner?p->owner->name : "" ,a->name ,
creator->op, a->offset,
a->offset + a->length,
p->h->buffer->ulength);
grib_accessor_delete(p->h->context,a);
2013-06-19 12:13:45 +00:00
return NULL;
} else {
grib_context_log(p->h->context,GRIB_LOG_DEBUG,
"CREATE: name=%s class=%s offset=%ld length=%ld action=",
a->name,a->cclass->name,a->offset,a->length);
grib_grow_buffer(p->h->context,p->h->buffer,size);
p->h->buffer->ulength = size;
}
}
if(p->owner)
grib_context_log(p->h->context, GRIB_LOG_DEBUG,
"Creating (%s)%s of %s at offset %d [len=%d]",
p->owner->name ,a->name ,creator->op, a->offset,len,p->block);
else
grib_context_log(p->h->context, GRIB_LOG_DEBUG,
"Creating root %s of %s at offset %d [len=%d]",
a->name ,creator->op, a->offset,len,p->block);
return a;
2013-03-25 12:04:10 +00:00
}
2015-02-26 18:28:42 +00:00
static void link_same_attributes(grib_accessor* a,grib_accessor* b) {
int i=0;
int idx=0;
grib_accessor* bAttribute=NULL;
if (a==NULL || b==NULL) return;
while (a->attributes[i] && i<MAX_ACCESSOR_ATTRIBUTES) {
bAttribute=_grib_accessor_get_attribute(b,a->attributes[i]->name,&idx);
if (bAttribute) a->attributes[i]->same=bAttribute;
i++;
}
}
2013-03-25 12:04:10 +00:00
void grib_push_accessor(grib_accessor* a, grib_block_of_accessors* l)
{
2013-06-19 12:13:45 +00:00
int id;
if (!l->first)
l->first = l->last = a;
else{
l->last->next = a;
a->previous = l->last;
}
l->last = a;
2013-03-25 12:04:10 +00:00
2013-06-19 12:13:45 +00:00
if (a->parent->h->use_trie) {
if (*(a->all_names[0]) != '_') {
id=grib_hash_keys_get_id(a->parent->h->context->keys,a->all_names[0]);
2013-03-25 12:04:10 +00:00
2013-06-19 12:13:45 +00:00
a->same=a->parent->h->accessors[id];
2015-02-26 18:28:42 +00:00
link_same_attributes(a,a->same);
2013-06-19 12:13:45 +00:00
a->parent->h->accessors[id]=a;
2013-03-25 12:04:10 +00:00
2013-06-19 12:13:45 +00:00
if(a->same == a) {
fprintf(stderr,"---> %s\n",a->name);
Assert(a->same != a);
}
}
2013-03-25 12:04:10 +00:00
}
}
void grib_section_post_init(grib_section* s)
{
2013-06-19 12:13:45 +00:00
grib_accessor* a = s ? s->block->first : NULL;
while(a ) {
grib_accessor_class* c=a->cclass;
if(c->post_init) c->post_init(a);
if (a->sub_section)
grib_section_post_init(a->sub_section);
a = a->next;
}
2013-03-25 12:04:10 +00:00
}
int grib_section_adjust_sizes(grib_section* s,int update,int depth)
2013-03-25 12:04:10 +00:00
{
int err = 0;
2013-06-19 12:13:45 +00:00
grib_accessor* a = s ? s->block->first : NULL;
size_t length = update ? 0 : (s?s->padding:0);
size_t offset = (s && s->owner) ? s->owner->offset:0;
int force_update = update > 1;
while(a) {
register long l;
/* grib_section_adjust_sizes(grib_get_sub_section(a),update,depth+1); */
err = grib_section_adjust_sizes(a->sub_section,update,depth+1);
if (err) return err;
2013-06-19 12:13:45 +00:00
l = a->length;
if(offset != a->offset) {
grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,
"Offset mismatch %s A->offset %ld offset %ld\n",a->name,(long)a->offset, (long)offset);
2013-06-19 12:13:45 +00:00
a->offset = offset;
return GRIB_DECODING_ERROR;
2013-06-19 12:13:45 +00:00
}
length += l;
offset += l;
a = a->next;
2013-03-25 12:04:10 +00:00
}
2013-06-19 12:13:45 +00:00
if(s)
2013-03-25 12:04:10 +00:00
{
2013-06-19 12:13:45 +00:00
if(s->aclength)
2013-03-25 12:04:10 +00:00
{
2013-06-19 12:13:45 +00:00
size_t len = 1;
long plen = 0;
int lret=grib_unpack_long(s->aclength, &plen, &len);
Assert( lret == GRIB_SUCCESS);
/* This happens when there is some padding */
if((plen != length) || force_update)
2013-03-25 12:04:10 +00:00
{
2013-06-19 12:13:45 +00:00
if(update)
{
plen = length;
lret=grib_pack_long(s->aclength, &plen, &len);
Assert(lret == GRIB_SUCCESS);
s->padding = 0;
}
else {
if(!s->h->partial) {
if(length >= plen)
{
grib_context_log(s->h->context,GRIB_LOG_ERROR,"Invalid size %ld found for %s, assuming %ld",
(long)plen,s->owner->name,(long)length);
plen = length;
}
s->padding = plen - length;
}
length = plen;
}
2013-03-25 12:04:10 +00:00
}
}
2013-06-19 12:13:45 +00:00
if(s->owner) s->owner->length = length;
s->length = length;
}
return err;
2013-03-25 12:04:10 +00:00
}
int grib_get_block_length(grib_section* s, size_t *l)
{
2013-06-19 12:13:45 +00:00
*l = s->length;
return GRIB_SUCCESS;
2013-03-25 12:04:10 +00:00
#if 0
2013-06-19 12:13:45 +00:00
/* TODO: Because grib_pack_long takes a SIGNED value, we may have problems */
if(s->aclength)
{
size_t len = 1;
long plen = 0;
2013-03-25 12:04:10 +00:00
2013-06-19 12:13:45 +00:00
int ret = grib_unpack_long(s->aclength, &plen, &len);
if(ret == GRIB_SUCCESS && plen != 0)
{
*l = plen;
return GRIB_SUCCESS;
}
}
2013-03-25 12:04:10 +00:00
2013-06-19 12:13:45 +00:00
/* empty block */
if(s->block->first == NULL)
2013-03-25 12:04:10 +00:00
{
2013-06-19 12:13:45 +00:00
*l = 0;
return GRIB_SUCCESS;
2013-03-25 12:04:10 +00:00
}
2013-06-19 12:13:45 +00:00
/* no accessor for block length */
if(s->owner)
*l = grib_get_next_position_offset(s->block->last) - s->owner->offset;
else
*l = grib_get_next_position_offset(s->block->last);
2013-03-25 12:04:10 +00:00
2013-06-19 12:13:45 +00:00
if(s->aclength)
{
size_t len = 1;
long plen = *l;
int ret = grib_pack_long(s->aclength, &plen, &len);
if(ret != GRIB_SUCCESS)
;
if(s->h->context->debug)
printf("SECTION updating length %ld %s\n",plen,s->owner->name);
}
/*
2013-03-25 12:04:10 +00:00
if(s->aclength)
Assert(*l == plen);*/
2013-06-19 12:13:45 +00:00
return GRIB_SUCCESS;
2013-03-25 12:04:10 +00:00
#endif
}
grib_accessor* find_paddings(grib_section* s)
{
2013-06-19 12:13:45 +00:00
grib_accessor* a = s ? s->block->first : NULL;
2013-03-25 12:04:10 +00:00
2013-06-19 12:13:45 +00:00
while(a)
{
/* grib_accessor* p = find_paddings(grib_get_sub_section(a)); */
grib_accessor* p = find_paddings(a->sub_section);
if(p) return p;
2013-03-25 12:04:10 +00:00
2013-06-19 12:13:45 +00:00
if(grib_preferred_size(a,0) != a->length)
return a;
2013-03-25 12:04:10 +00:00
2013-06-19 12:13:45 +00:00
a = a->next;
}
2013-03-25 12:04:10 +00:00
2013-06-19 12:13:45 +00:00
return NULL;
2013-03-25 12:04:10 +00:00
}
void grib_update_paddings(grib_section* s)
{
2013-06-19 12:13:45 +00:00
grib_accessor* last = NULL;
grib_accessor* changed;
/* while((changed = find_paddings(s)) != NULL) */
while((changed = find_paddings(s->h->root)) != NULL)
{
Assert(changed != last);
grib_resize(changed,grib_preferred_size(changed,0));
last = changed;
}
2013-03-25 12:04:10 +00:00
}