/* * 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 * * * ***************************************************************************/ #include "grib_api_internal.h" void grib_get_buffer_ownership(const grib_context *c, grib_buffer *b) { unsigned char* newdata; if(b->property == GRIB_MY_BUFFER) return; newdata = (unsigned char*)grib_context_malloc(c, b->length); memcpy(newdata, b->data, b->length); b->data = newdata; b->property = GRIB_MY_BUFFER; } grib_buffer* grib_create_growable_buffer(const grib_context* c) { grib_buffer *b = (grib_buffer*)grib_context_malloc_clear(c,sizeof(grib_buffer)); if(b == NULL) { grib_context_log(c,GRIB_LOG_ERROR,"grib_new_buffer: cannot allocate buffer"); return NULL; } b->property = GRIB_MY_BUFFER; b->length = 10240; b->ulength = 0; b->data = (unsigned char*)grib_context_malloc_clear(c,b->length); b->growable = 1; if(!b->data) { grib_context_log(c,GRIB_LOG_ERROR,"grib_new_buffer: cannot allocate buffer"); grib_context_free(c,b); return NULL; } return b; } grib_buffer* grib_new_buffer(const grib_context* c, const unsigned char* data, size_t buflen) { grib_buffer *b = (grib_buffer*)grib_context_malloc_clear(c,sizeof(grib_buffer)); if(b == NULL) { grib_context_log(c,GRIB_LOG_ERROR,"grib_new_buffer: cannot allocate buffer"); return NULL; } b->property = GRIB_USER_BUFFER; b->length = buflen; b->ulength = buflen; b->ulength_bits = buflen*8; b->data = (unsigned char*)data; return b; } void grib_buffer_delete(const grib_context *c, grib_buffer *b) { if(b->property == GRIB_MY_BUFFER) grib_context_free(c,b->data); b->length = 0; b->ulength = 0; grib_context_free(c,b); } static void grib_grow_buffer_to(const grib_context *c, grib_buffer *b, size_t ns) { unsigned char* newdata; if(ns>b->length) { grib_get_buffer_ownership(c, b); newdata = (unsigned char*)grib_context_malloc_clear(c, ns); memcpy(newdata, b->data, b->length); grib_context_free(c,b->data); b->data = newdata; b->length = ns; } } void grib_grow_buffer(const grib_context *c, grib_buffer *b, size_t new_size) { size_t len = ((new_size + 1023)/1024)*1024; grib_grow_buffer_to(c,b,len); } void grib_buffer_set_ulength_bits(const grib_context *c, grib_buffer *b, size_t length_bits) { size_t length=length_bits/8; if (length_bits%8) length++; grib_grow_buffer_to(c,b,length); b->ulength_bits = length_bits; b->ulength = length; } void grib_buffer_set_ulength(const grib_context *c, grib_buffer *b, size_t length) { grib_grow_buffer_to(c,b,length); b->ulength = length; b->ulength_bits = length*8; } static void update_offsets(grib_accessor* a,long len) { while(a) { grib_section* s = a->sub_section; a->offset += len; grib_context_log(a->context,GRIB_LOG_DEBUG, "::::: grib_buffer : accessor %s is moving by %d bytes to %ld",a->name ,len, a->offset); if(s) update_offsets(s->block->first,len); a = a->next; } } static void update_offsets_after(grib_accessor* a,long len) { while(a) { update_offsets(a->next,len); a = a->parent->owner; } } #if 0 /* new GCC compiler v4.5.0 complains function is defined but not used*/ void grib_recompute_sections_lengths(grib_section* s) { if(s) { long plen = 0; size_t len = 1; grib_accessor* a = s->block->first; while(a) { /* grib_recompute_sections_lengths(grib_get_sub_section(a)); */ grib_recompute_sections_lengths(a->sub_section); a = a->next; } if(s->aclength) { int ret; if(s->owner) plen = grib_get_next_position_offset(s->block->last) - s->owner->offset; else plen = grib_get_next_position_offset(s->block->last); if((ret = grib_pack_long(s->aclength, &plen, &len)) != GRIB_SUCCESS) ; #if 0 if(s->h->context->debug) printf("SECTION updating length %ld .. %s\n",plen,s->owner->name); #endif } } } #endif #if 0 /* new GCC compiler v4.5.0 complains function is defined but not used*/ static void update_sections_lengths(grib_section* s) { long plen = 0; size_t len = 1; if(!s) return; if(s->aclength) { int ret; if(s->owner) plen = grib_get_next_position_offset(s->block->last) - s->owner->offset; else plen = grib_get_next_position_offset(s->block->last); /* if(s->owner) */ /* s->owner->length = plen; */ /* if(s->aclength) */ if((ret = grib_pack_long(s->aclength, &plen, &len)) != GRIB_SUCCESS) ; if(s->h->context->debug) { printf("SECTION updating length %ld .. %s\n",plen,s->owner->name); printf("NEXT_POS = %ld, owner offset= %ld %s %s\n", grib_get_next_position_offset(s->block->last), s->owner ? s->owner->offset : 0L, s->owner->name, s->block->last->name); } } if(s->owner) update_sections_lengths(s->owner->parent); } #endif void grib_buffer_replace( grib_accessor *a, const unsigned char* data, size_t newsize,int update_lengths,int update_paddings) { size_t offset = a->offset; long oldsize = grib_get_next_position_offset(a)-offset; long increase = (long)newsize - (long)oldsize; grib_buffer *buffer = grib_handle_of_accessor(a)->buffer; size_t message_length = buffer->ulength; grib_context_log(a->context,GRIB_LOG_DEBUG, "grib_buffer_replace %s offset=%ld oldsize=%ld newsize=%ld message_length=%ld update_paddings=%d", a->name,(long)offset,oldsize,(long)newsize,(long)message_length,update_paddings); grib_buffer_set_ulength(a->context, buffer, buffer->ulength+increase); /* move the end */ if(increase) memmove( buffer->data + offset + newsize, buffer->data + offset + oldsize, message_length - offset - oldsize); /* copy new data */ DebugAssert( buffer->data + offset ); DebugAssert( data || (newsize==0) );/* if data==NULL then newsize must be 0 */ if (data) { /* Note: memcpy behaviour is undefined if either dest or src is NULL */ memcpy(buffer->data + offset, data, newsize); } if(increase) { update_offsets_after(a,increase); if(update_lengths) { grib_update_size(a,newsize); grib_section_adjust_sizes(grib_handle_of_accessor(a)->root,1,0); if(update_paddings) grib_update_paddings(grib_handle_of_accessor(a)->root); } } } void grib_update_sections_lengths(grib_handle* h) { grib_section_adjust_sizes(h->root,2,0); grib_update_paddings(h->root); }