1 /*
2  * (C) Copyright 2005- ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  *
7  * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
8  * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
9  */
10 
11 /***************************************************************************
12  *   Jean Baptiste Filippi - 01.11.2005
13  *   Enrico Fucile
14  *                                                                         *
15  ***************************************************************************/
16 #include "grib_api_internal.h"
17 
18 #if 0
19  /* #if GRIB_PTHREADS */
20  static pthread_once_t once  = PTHREAD_ONCE_INIT;
21  static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
22  static pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
23  static void init() {
24 	pthread_mutexattr_t attr;
25 	pthread_mutexattr_init(&attr);
26 	pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
27 	pthread_mutex_init(&mutex1,&attr);
28 	pthread_mutex_init(&mutex2,&attr);
29 	pthread_mutexattr_destroy(&attr);
30  }
31  /* #elif GRIB_OMP_THREADS */
32  static int once = 0;
33  static omp_nest_lock_t mutex1;
34  static omp_nest_lock_t mutex2;
35  static void init()
36  {
37     GRIB_OMP_CRITICAL(lock_grib_handle_c)
38     {
39         if (once == 0)
40         {
41             omp_init_nest_lock(&mutex1);
42             omp_init_nest_lock(&mutex2);
43             once = 1;
44         }
45     }
46  }
47 #endif
48 
49 static grib_handle* grib_handle_new_from_file_no_multi(grib_context* c, FILE* f, int headers_only, int* error);
50 static grib_handle* grib_handle_new_from_file_multi(grib_context* c, FILE* f, int* error);
51 static int grib2_get_next_section(unsigned char* msgbegin, size_t msglen, unsigned char** secbegin, size_t* seclen, int* secnum, int* err);
52 static int grib2_has_next_section(unsigned char* msgbegin, size_t msglen, unsigned char* secbegin, size_t seclen, int* err);
53 static void grib2_build_message(grib_context* context, unsigned char* sections[], size_t sections_len[], void** data, size_t* msglen);
54 static grib_multi_support* grib_get_multi_support(grib_context* c, FILE* f);
55 static grib_multi_support* grib_multi_support_new(grib_context* c);
56 static grib_handle* grib_handle_new_multi(grib_context* c, unsigned char** idata, size_t* buflen, int* error);
57 
58 /* Note: A fast cut-down version of strcmp which does NOT return -1 */
59 /* 0 means input strings are equal and 1 means not equal */
grib_inline_strcmp(const char * a,const char * b)60 static GRIB_INLINE int grib_inline_strcmp(const char* a, const char* b)
61 {
62     if (*a != *b)
63         return 1;
64     while ((*a != 0 && *b != 0) && *(a) == *(b)) {
65         a++;
66         b++;
67     }
68     return (*a == 0 && *b == 0) ? 0 : 1;
69 }
70 
grib_section_create(grib_handle * h,grib_accessor * owner)71 grib_section* grib_section_create(grib_handle* h, grib_accessor* owner)
72 {
73     grib_section* s = (grib_section*)grib_context_malloc_clear(h->context, sizeof(grib_section));
74     s->owner        = owner;
75     s->aclength     = NULL;
76     s->h            = h;
77     s->block        = (grib_block_of_accessors*)grib_context_malloc_clear(h->context, sizeof(grib_block_of_accessors));
78     return s;
79 }
80 
update_sections(grib_section * s,grib_handle * h,long offset)81 static void update_sections(grib_section* s, grib_handle* h, long offset)
82 {
83     grib_accessor* a = s ? s->block->first : NULL;
84     if (s)
85         s->h = h;
86     while (a) {
87         a->offset += offset;
88         /* update_sections ( grib_get_sub_section ( a ),h,offset ); */
89         update_sections(a->sub_section, h, offset);
90         a = a->next;
91     }
92 }
93 
grib_swap_sections(grib_section * the_old,grib_section * the_new)94 void grib_swap_sections(grib_section* the_old, grib_section* the_new)
95 {
96     grib_accessor* a;
97     grib_block_of_accessors* b = the_old->block;
98 
99     /* printf("SWAPPING -----\n"); grib_dump_section_content(new,stdout); */
100     the_old->block = the_new->block;
101     the_new->block = b;
102 
103     a                 = the_old->aclength;
104     the_old->aclength = the_new->aclength;
105     the_new->aclength = a;
106 
107     a = the_old->block->first;
108     while (a) {
109         a->parent = the_old;
110         a         = a->next;
111     }
112 
113     update_sections(the_old, the_old->h, the_old->owner->offset);
114     /* update_sections(new,new->h,new->owner->offset); */
115 
116     /* printf("SWAPPING -----\n"); grib_dump_section_content(old,stdout); */
117 }
118 
grib_empty_section(grib_context * c,grib_section * b)119 void grib_empty_section(grib_context* c, grib_section* b)
120 {
121     grib_accessor* current = NULL;
122     if (!b)
123         return;
124 
125     b->aclength = NULL;
126 
127     current = b->block->first;
128 
129     while (current) {
130         grib_accessor* next = current->next;
131         if (current->sub_section) {
132             grib_section_delete(c, current->sub_section);
133             current->sub_section = 0;
134         }
135         grib_accessor_delete(c, current);
136         current = next;
137     }
138     b->block->first = b->block->last = 0;
139 }
140 
grib_section_delete(grib_context * c,grib_section * b)141 void grib_section_delete(grib_context* c, grib_section* b)
142 {
143     if (!b)
144         return;
145 
146     grib_empty_section(c, b);
147     grib_context_free(c, b->block);
148     /* printf("++++ deleted %p\n",b); */
149     grib_context_free(c, b);
150 }
151 
grib_handle_delete(grib_handle * h)152 int grib_handle_delete(grib_handle* h)
153 {
154     if (h != NULL) {
155         grib_context* ct   = h->context;
156         grib_dependency* d = h->dependencies;
157         grib_dependency* n;
158 
159         if (h->kid != NULL)
160             return GRIB_INTERNAL_ERROR;
161 
162         while (d) {
163             n = d->next;
164             grib_context_free(ct, d);
165             d = n;
166         }
167         h->dependencies = 0;
168 
169         grib_buffer_delete(ct, h->buffer);
170         grib_section_delete(ct, h->root);
171         grib_context_free(ct, h->gts_header);
172 
173         grib_context_log(ct, GRIB_LOG_DEBUG, "grib_handle_delete: deleting handle %p", (void*)h);
174         grib_context_free(ct, h);
175         h = NULL;
176     }
177     return GRIB_SUCCESS;
178 }
179 
grib_new_handle(grib_context * c)180 grib_handle* grib_new_handle(grib_context* c)
181 {
182     grib_handle* g = NULL;
183     if (c == NULL)
184         c = grib_context_get_default();
185     g = (grib_handle*)grib_context_malloc_clear(c, sizeof(grib_handle));
186 
187     if (g == NULL) {
188         grib_context_log(c, GRIB_LOG_ERROR, "grib_new_handle: cannot allocate handle");
189     }
190     else {
191         g->context      = c;
192         g->product_kind = PRODUCT_ANY; /* Default. Will later be set to a specific product */
193     }
194 
195     grib_context_log(c, GRIB_LOG_DEBUG, "grib_new_handle: allocated handle %p", (void*)g);
196 
197     return g;
198 }
199 
grib_handle_create(grib_handle * gl,grib_context * c,const void * data,size_t buflen)200 static grib_handle* grib_handle_create(grib_handle* gl, grib_context* c, const void* data, size_t buflen)
201 {
202     grib_action* next = NULL;
203     int err           = 0;
204 
205     if (gl == NULL)
206         return NULL;
207 
208     gl->use_trie     = 1;
209     gl->trie_invalid = 0;
210     gl->buffer       = grib_new_buffer(gl->context, (const unsigned char*)data, buflen);
211 
212     if (gl->buffer == NULL) {
213         grib_handle_delete(gl);
214         return NULL;
215     }
216 
217     gl->root = grib_create_root_section(gl->context, gl);
218 
219     if (!gl->root) {
220         grib_context_log(c, GRIB_LOG_ERROR, "grib_handle_create: cannot create root section");
221         grib_handle_delete(gl);
222         return NULL;
223     }
224 
225     if (!gl->context->grib_reader || !gl->context->grib_reader->first) {
226         grib_context_log(c, GRIB_LOG_ERROR, "grib_handle_create: cannot create handle, no definitions found");
227         grib_handle_delete(gl);
228         return NULL;
229     }
230 
231     gl->buffer->property = GRIB_USER_BUFFER;
232 
233     next = gl->context->grib_reader->first->root;
234     while (next) {
235         if (grib_create_accessor(gl->root, next, NULL) != GRIB_SUCCESS)
236             break;
237         next = next->next;
238     }
239 
240     err = grib_section_adjust_sizes(gl->root, 0, 0);
241     if (err) {
242         grib_handle_delete(gl);
243         return NULL;
244     }
245 
246     grib_section_post_init(gl->root);
247 
248     return gl;
249 }
250 
grib_handle_new_from_samples(grib_context * c,const char * name)251 grib_handle* grib_handle_new_from_samples(grib_context* c, const char* name)
252 {
253     grib_handle* g = 0;
254     if (c == NULL)
255         c = grib_context_get_default();
256     grib_context_set_handle_file_count(c, 0);
257     grib_context_set_handle_total_count(c, 0);
258 
259     /*
260      * g = grib_internal_sample(c,name);
261      * if(g) return g;
262      */
263     if (c->debug) {
264         fprintf(stderr, "ECCODES DEBUG grib_handle_new_from_samples '%s'\n", name);
265     }
266 
267     g = grib_external_template(c, name);
268     if (!g)
269         grib_context_log(c, GRIB_LOG_ERROR,
270                          "Unable to load sample file '%s.tmpl'\n"
271                          "                   from %s\n"
272                          "                   (ecCodes Version=%s)",
273                          name, c->grib_samples_path, ECCODES_VERSION_STR);
274 
275     return g;
276 }
277 
codes_bufr_handle_new_from_samples(grib_context * c,const char * name)278 grib_handle* codes_bufr_handle_new_from_samples(grib_context* c, const char* name)
279 {
280     grib_handle* g = 0;
281     if (c == NULL)
282         c = grib_context_get_default();
283     grib_context_set_handle_file_count(c, 0);
284     grib_context_set_handle_total_count(c, 0);
285 
286     /*
287      *  g = grib_internal_sample(c,name);
288      *  if(g) return g;
289      */
290     if (c->debug) {
291         fprintf(stderr, "ECCODES DEBUG codes_bufr_handle_new_from_samples '%s'\n", name);
292     }
293 
294     g = bufr_external_template(c, name);
295     if (!g)
296         grib_context_log(c, GRIB_LOG_ERROR,
297                          "Unable to load sample file '%s.tmpl'\n"
298                          "                   from %s\n"
299                          "                   (ecCodes Version=%s)",
300                          name, c->grib_samples_path, ECCODES_VERSION_STR);
301 
302     return g;
303 }
304 
grib_write_message(const grib_handle * h,const char * file,const char * mode)305 int grib_write_message(const grib_handle* h, const char* file, const char* mode)
306 {
307     FILE* fh = 0;
308     int err;
309     const void* buffer;
310     size_t size;
311 
312     fh = fopen(file, mode);
313     if (!fh) {
314         perror(file);
315         return GRIB_IO_PROBLEM;
316     }
317     err = grib_get_message(h, &buffer, &size);
318     if (err) {
319         fclose(fh);
320         return err;
321     }
322 
323     if (fwrite(buffer, 1, size, fh) != size) {
324         perror(file);
325         fclose(fh);
326         return GRIB_IO_PROBLEM;
327     }
328     if (fclose(fh) != 0) {
329         perror(file);
330         return GRIB_IO_PROBLEM;
331     }
332     return 0;
333 }
334 
grib_handle_clone(const grib_handle * h)335 grib_handle* grib_handle_clone(const grib_handle* h)
336 {
337     grib_handle* result  = grib_handle_new_from_message_copy(h->context, h->buffer->data, h->buffer->ulength);
338     result->product_kind = h->product_kind;
339     return result;
340 }
341 
codes_handle_new_from_file(grib_context * c,FILE * f,ProductKind product,int * error)342 grib_handle* codes_handle_new_from_file(grib_context* c, FILE* f, ProductKind product, int* error)
343 {
344     if (product == PRODUCT_GRIB)
345         return grib_handle_new_from_file(c, f, error);
346     if (product == PRODUCT_BUFR)
347         return bufr_new_from_file(c, f, error);
348     if (product == PRODUCT_METAR)
349         return metar_new_from_file(c, f, error);
350     if (product == PRODUCT_GTS)
351         return gts_new_from_file(c, f, error);
352     if (product == PRODUCT_ANY)
353         return any_new_from_file(c, f, error);
354 
355     Assert(!"codes_handle_new_from_file: Invalid product");
356     return NULL;
357 }
358 
codes_grib_handle_new_from_file(grib_context * c,FILE * f,int * error)359 grib_handle* codes_grib_handle_new_from_file(grib_context* c, FILE* f, int* error)
360 {
361     return grib_handle_new_from_file(c, f, error);
362 }
codes_bufr_handle_new_from_file(grib_context * c,FILE * f,int * error)363 grib_handle* codes_bufr_handle_new_from_file(grib_context* c, FILE* f, int* error)
364 {
365     return bufr_new_from_file(c, f, error);
366 }
codes_metar_handle_new_from_file(grib_context * c,FILE * f,int * error)367 grib_handle* codes_metar_handle_new_from_file(grib_context* c, FILE* f, int* error)
368 {
369     return metar_new_from_file(c, f, error);
370 }
codes_gts_handle_new_from_file(grib_context * c,FILE * f,int * error)371 grib_handle* codes_gts_handle_new_from_file(grib_context* c, FILE* f, int* error)
372 {
373     return gts_new_from_file(c, f, error);
374 }
375 
determine_product_kind(grib_handle * h,ProductKind * prod_kind)376 static int determine_product_kind(grib_handle* h, ProductKind* prod_kind)
377 {
378     int err    = 0;
379     size_t len = 0;
380     err        = grib_get_length(h, "identifier", &len);
381     if (!err) {
382         char id_str[64] = {0,};
383         err = grib_get_string(h, "identifier", id_str, &len);
384         if (grib_inline_strcmp(id_str, "GRIB") == 0)
385             *prod_kind = PRODUCT_GRIB;
386         else if (grib_inline_strcmp(id_str, "BUFR") == 0)
387             *prod_kind = PRODUCT_BUFR;
388         else if (grib_inline_strcmp(id_str, "METAR") == 0)
389             *prod_kind = PRODUCT_METAR;
390         else if (grib_inline_strcmp(id_str, "GTS") == 0)
391             *prod_kind = PRODUCT_GTS;
392         else if (grib_inline_strcmp(id_str, "TAF") == 0)
393             *prod_kind = PRODUCT_TAF;
394         else
395             *prod_kind = PRODUCT_ANY;
396     }
397     return err;
398 }
399 
grib_handle_new_from_message_copy(grib_context * c,const void * data,size_t size)400 grib_handle* grib_handle_new_from_message_copy(grib_context* c, const void* data, size_t size)
401 {
402     grib_handle* g = NULL;
403     void* copy     = NULL;
404     if (c == NULL)
405         c = grib_context_get_default();
406 
407     grib_context_set_handle_file_count(c, 0);
408     grib_context_set_handle_total_count(c, 0);
409     copy = grib_context_malloc(c, size);
410     if (!copy) {
411         return NULL;
412     }
413 
414     memcpy(copy, data, size);
415 
416     g                   = grib_handle_new_from_message(c, copy, size);
417     g->buffer->property = GRIB_MY_BUFFER;
418 
419     return g;
420 }
421 
grib_handle_new_from_partial_message_copy(grib_context * c,const void * data,size_t size)422 grib_handle* grib_handle_new_from_partial_message_copy(grib_context* c, const void* data, size_t size)
423 {
424     grib_handle* g = NULL;
425     void* copy     = NULL;
426     if (c == NULL)
427         c = grib_context_get_default();
428     grib_context_set_handle_file_count(c, 0);
429     grib_context_set_handle_total_count(c, 0);
430     copy = grib_context_malloc(c, size);
431     if (!copy)
432         return NULL;
433 
434     memcpy(copy, data, size);
435 
436     g                   = grib_handle_new_from_partial_message(c, copy, size);
437     g->buffer->property = GRIB_MY_BUFFER;
438 
439     return g;
440 }
441 
grib_handle_new_from_partial_message(grib_context * c,const void * data,size_t buflen)442 grib_handle* grib_handle_new_from_partial_message(grib_context* c, const void* data, size_t buflen)
443 {
444     grib_handle* gl = NULL;
445     if (c == NULL)
446         c = grib_context_get_default();
447     grib_context_set_handle_file_count(c, 0);
448     grib_context_set_handle_total_count(c, 0);
449     gl          = grib_new_handle(c);
450     gl->partial = 1;
451     return grib_handle_create(gl, c, data, buflen);
452 }
453 
grib_handle_new_from_message(grib_context * c,const void * data,size_t buflen)454 grib_handle* grib_handle_new_from_message(grib_context* c, const void* data, size_t buflen)
455 {
456     grib_handle* gl          = NULL;
457     grib_handle* h           = NULL;
458     ProductKind product_kind = PRODUCT_ANY;
459     if (c == NULL)
460         c = grib_context_get_default();
461     gl               = grib_new_handle(c);
462     gl->product_kind = PRODUCT_GRIB; /* See ECC-480 */
463     h                = grib_handle_create(gl, c, data, buflen);
464 
465     /* See ECC-448 */
466     if (determine_product_kind(h, &product_kind) == GRIB_SUCCESS) {
467         h->product_kind = product_kind;
468     }
469 
470     if (h->product_kind == PRODUCT_GRIB) {
471         if (!grib_is_defined(h, "7777")) {
472             grib_context_log(c, GRIB_LOG_ERROR, "grib_handle_new_from_message: No final 7777 in message!");
473             /* TODO: Return NULL. An incomplete message is no use to anyone.
474              * But first check the MARS Client and other applications
475              */
476         }
477     }
478     return h;
479 }
480 
grib_handle_new_from_multi_message(grib_context * c,void ** data,size_t * buflen,int * error)481 grib_handle* grib_handle_new_from_multi_message(grib_context* c, void** data,
482                                                 size_t* buflen, int* error)
483 {
484     grib_handle* h    = NULL;
485     unsigned char** d = (unsigned char**)data;
486     if (c == NULL)
487         c = grib_context_get_default();
488 
489     if (c->multi_support_on)
490         h = grib_handle_new_multi(c, d, buflen, error);
491     else {
492         size_t olen   = 0;
493         void* message = NULL;
494         *error        = grib_read_any_from_memory_alloc(c, d, buflen, &message, &olen);
495         if (message == NULL)
496             return NULL;
497         h = grib_new_handle(c);
498         grib_handle_create(h, c, message, olen);
499     }
500 
501     return h;
502 }
503 
grib_handle_new_from_file(grib_context * c,FILE * f,int * error)504 grib_handle* grib_handle_new_from_file(grib_context* c, FILE* f, int* error)
505 {
506     return grib_new_from_file(c, f, 0, error);
507 }
508 
grib_handle_new_multi(grib_context * c,unsigned char ** data,size_t * buflen,int * error)509 static grib_handle* grib_handle_new_multi(grib_context* c, unsigned char** data,
510                                           size_t* buflen, int* error)
511 {
512     void* message = NULL;
513     size_t olen = 0, len = 0;
514     grib_handle* gl         = NULL;
515     long edition            = 0;
516     size_t seclen           = 0;
517     unsigned char* secbegin = 0;
518     int secnum = 0, seccount = 0;
519     int err = 0, i = 0;
520     grib_multi_support* gm = NULL;
521 
522     if (c == NULL)
523         c = grib_context_get_default();
524 
525     gm = grib_get_multi_support(c, 0);
526 
527     if (!gm->message) {
528         *error             = grib_read_any_from_memory_alloc(c, data, buflen, &message, &olen);
529         gm->message_length = olen;
530         gm->message        = (unsigned char*)message;
531         if (*error != GRIB_SUCCESS || !message) {
532             if (*error == GRIB_END_OF_FILE)
533                 *error = GRIB_SUCCESS;
534             gm->message_length = 0;
535             return NULL;
536         }
537     }
538     else {
539         message = gm->message;
540     }
541 
542     edition = grib_decode_unsigned_byte_long((const unsigned char*)message, 7, 1);
543 
544     if (edition == 2) {
545         olen = gm->message_length;
546         if (gm->section_number == 0) {
547             gm->sections[0] = (unsigned char*)message;
548         }
549         secbegin = gm->sections[gm->section_number];
550         seclen   = gm->sections_length[gm->section_number];
551         secnum   = gm->section_number;
552         seccount = 0;
553         while (grib2_get_next_section((unsigned char*)message, olen, &secbegin, &seclen, &secnum, &err)) {
554             seccount++;
555             /*printf("   - %d - section %d length=%d\n",(int)seccount,(int)secnum,(int)seclen);*/
556 
557             gm->sections[secnum]        = secbegin;
558             gm->sections_length[secnum] = seclen;
559 
560             if (secnum == 6) {
561                 /* Special case for inherited bitmaps */
562                 if (grib_decode_unsigned_byte_long(secbegin, 5, 1) == 254) {
563                     if (!gm->bitmap_section) {
564                         grib_context_log(c, GRIB_LOG_ERROR,
565                                          "grib_handle_new_multi : cannot create handle, missing bitmap\n");
566                         return NULL;
567                     }
568                     gm->sections[secnum]        = gm->bitmap_section;
569                     gm->sections_length[secnum] = gm->bitmap_section_length;
570                 }
571                 else {
572                     if (gm->bitmap_section) {
573                         grib_context_free(c, gm->bitmap_section);
574                         gm->bitmap_section = NULL;
575                     }
576                     gm->bitmap_section        = (unsigned char*)grib_context_malloc(c, seclen);
577                     gm->bitmap_section        = (unsigned char*)memcpy(gm->bitmap_section, secbegin, seclen);
578                     gm->bitmap_section_length = seclen;
579                 }
580             }
581 
582             if (secnum == 7) {
583                 void* p = message;
584                 len     = olen;
585                 grib2_build_message(c, gm->sections, gm->sections_length, &message, &len);
586 
587                 if (grib2_has_next_section((unsigned char*)p, olen, secbegin, seclen, &err)) {
588                     gm->message        = (unsigned char*)p;
589                     gm->section_number = secnum;
590                     olen               = len;
591                 }
592                 else {
593                     grib_context_free(c, gm->message);
594                     gm->message = NULL;
595                     for (i = 0; i < 8; i++)
596                         gm->sections[i] = NULL;
597                     gm->section_number = 0;
598                     gm->message_length = 0;
599                     olen               = len;
600                 }
601 
602                 break;
603             }
604         }
605     }
606     else if (edition == 3) {
607         *error = GRIB_UNSUPPORTED_EDITION;
608         return NULL;
609     }
610     else {
611         gm->message_length = 0;
612         gm->message        = NULL;
613     }
614 
615     gl = grib_handle_new_from_message(c, message, olen);
616     if (!gl) {
617         *error = GRIB_DECODING_ERROR;
618         grib_context_log(c, GRIB_LOG_ERROR, "grib_handle_new_multi: cannot create handle \n");
619         return NULL;
620     }
621 
622     gl->buffer->property = GRIB_MY_BUFFER;
623     grib_context_increment_handle_file_count(c);
624     grib_context_increment_handle_total_count(c);
625 
626     return gl;
627 }
628 
grib_handle_new_from_file_multi(grib_context * c,FILE * f,int * error)629 static grib_handle* grib_handle_new_from_file_multi(grib_context* c, FILE* f, int* error)
630 {
631     void *data = NULL, *old_data = NULL;
632     size_t olen = 0, len = 0;
633     grib_handle* gl         = NULL;
634     long edition            = 0;
635     size_t seclen           = 0;
636     unsigned char* secbegin = 0;
637     int secnum = 0, seccount = 0;
638     int err = 0, i = 0;
639     grib_multi_support* gm  = NULL;
640     off_t gts_header_offset = 0;
641     off_t end_msg_offset = 0, offset = 0;
642     char *gts_header = 0, *save_gts_header = 0;
643     int gtslen = 0;
644 
645     if (c == NULL)
646         c = grib_context_get_default();
647 
648     gm = grib_get_multi_support(c, f);
649 
650     if (!gm->message) {
651         gts_header_offset = grib_context_tell(c, f);
652         data              = wmo_read_grib_from_file_malloc(f, 0, &olen, &offset, error);
653         end_msg_offset    = grib_context_tell(c, f);
654 
655         gm->message_length = olen;
656         gm->message        = (unsigned char*)data;
657         gm->offset         = offset;
658         if (*error != GRIB_SUCCESS || !data) {
659             if (data)
660                 grib_context_free(c, data);
661 
662             if (*error == GRIB_END_OF_FILE)
663                 *error = GRIB_SUCCESS;
664             gm->message_length = 0;
665             gm->message        = NULL;
666             return NULL;
667         }
668         if (c->gts_header_on) {
669             int g = 0;
670             grib_context_seek(c, gts_header_offset, SEEK_SET, f);
671             gtslen          = offset - gts_header_offset;
672             gts_header      = (char*)grib_context_malloc_clear(c, sizeof(unsigned char) * gtslen);
673             save_gts_header = gts_header;
674             grib_context_read(c, gts_header, gtslen, f);
675             g = gtslen;
676             while (gts_header != NULL && g != 0 && *gts_header != '\03') {
677                 /*printf("--------%d %X \n",gtslen,*gts_header);*/
678                 gts_header++;
679                 g--;
680             }
681             if (g > 8) {
682                 gts_header++;
683                 gtslen = g - 1;
684             }
685             else
686                 gts_header = save_gts_header;
687             grib_context_seek(c, end_msg_offset, SEEK_SET, f);
688         }
689     }
690     else
691         data = gm->message;
692 
693     edition = grib_decode_unsigned_byte_long((const unsigned char*)data, 7, 1);
694 
695     if (edition == 2) {
696         olen = gm->message_length;
697         if (gm->section_number == 0) {
698             gm->sections[0] = (unsigned char*)data;
699         }
700         secbegin = gm->sections[gm->section_number];
701         seclen   = gm->sections_length[gm->section_number];
702         secnum   = gm->section_number;
703         seccount = 0;
704         while (grib2_get_next_section((unsigned char*)data, olen, &secbegin, &seclen, &secnum, &err)) {
705             seccount++;
706             /*printf("   - %d - section %d length=%d\n",(int)seccount,(int)secnum,(int)seclen);*/
707 
708             gm->sections[secnum]        = secbegin;
709             gm->sections_length[secnum] = seclen;
710 
711             if (secnum == 6) {
712                 /* Special case for inherited bitmaps */
713                 if (grib_decode_unsigned_byte_long(secbegin, 5, 1) == 254) {
714                     if (!gm->bitmap_section) {
715                         grib_context_log(c, GRIB_LOG_ERROR, "grib_handle_new_from_file_multi: cannot create handle, missing bitmap\n");
716                         grib_context_free(c, data);
717                         return NULL;
718                     }
719                     gm->sections[secnum]        = gm->bitmap_section;
720                     gm->sections_length[secnum] = gm->bitmap_section_length;
721                 }
722                 else {
723                     if (gm->bitmap_section) {
724                         grib_context_free(c, gm->bitmap_section);
725                         gm->bitmap_section = NULL;
726                     }
727                     gm->bitmap_section        = (unsigned char*)grib_context_malloc(c, seclen);
728                     gm->bitmap_section        = (unsigned char*)memcpy(gm->bitmap_section, secbegin, seclen);
729                     gm->bitmap_section_length = seclen;
730                 }
731             }
732 
733             if (secnum == 7) {
734                 old_data = data;
735                 len      = olen;
736                 grib2_build_message(c, gm->sections, gm->sections_length, &data, &len);
737 
738                 if (grib2_has_next_section((unsigned char*)old_data, olen, secbegin, seclen, &err)) {
739                     gm->message        = (unsigned char*)old_data;
740                     gm->section_number = secnum;
741                     olen               = len;
742                 }
743                 else {
744                     if (gm->message)
745                         grib_context_free(c, gm->message);
746                     gm->message = NULL;
747                     for (i = 0; i < 8; i++)
748                         gm->sections[i] = NULL;
749                     gm->section_number = 0;
750                     gm->message_length = 0;
751                     olen               = len;
752                 }
753                 break;
754             }
755         }
756     }
757     else if (edition == 3) {
758         /* GRIB3: Multi-field mode not yet supported */
759         printf("WARNING: %s\n", "grib_handle_new_from_file_multi: GRIB3 multi-field mode not yet implemented! Reverting to single-field mode");
760         gm->message_length = 0;
761         gm->message        = NULL;
762     }
763     else {
764         gm->message_length = 0;
765         gm->message        = NULL;
766     }
767 
768     gl = grib_handle_new_from_message(c, data, olen);
769     if (!gl) {
770         *error = GRIB_DECODING_ERROR;
771         grib_context_log(c, GRIB_LOG_ERROR, "grib_handle_new_from_file_multi: cannot create handle \n");
772         grib_context_free(c, data);
773         return NULL;
774     }
775 
776     gl->offset           = gm->offset;
777     gl->buffer->property = GRIB_MY_BUFFER;
778     grib_context_increment_handle_file_count(c);
779     grib_context_increment_handle_total_count(c);
780 
781     if (c->gts_header_on && gtslen >= 8) {
782         gl->gts_header = (char*)grib_context_malloc_clear(c, sizeof(unsigned char) * gtslen);
783         DebugAssert(gts_header);
784         if (gts_header) memcpy(gl->gts_header, gts_header, gtslen);
785         gl->gts_header_len = gtslen;
786         grib_context_free(c, save_gts_header);
787     }
788     else {
789         gl->gts_header = NULL;
790     }
791 
792     return gl;
793 }
794 
grib_new_from_file(grib_context * c,FILE * f,int headers_only,int * error)795 grib_handle* grib_new_from_file(grib_context* c, FILE* f, int headers_only, int* error)
796 {
797     grib_handle* h = 0;
798     if (!f) {
799         *error = GRIB_IO_PROBLEM;
800         return NULL;
801     }
802 
803     if (c == NULL)
804         c = grib_context_get_default();
805 
806     if (c->multi_support_on)
807         h = grib_handle_new_from_file_multi(c, f, error);
808     else
809         h = grib_handle_new_from_file_no_multi(c, f, headers_only, error);
810 
811     if (h && h->offset == 0)
812         grib_context_set_handle_file_count(c, 1);
813 
814     if (h) {
815         h->product_kind = PRODUCT_GRIB;
816     }
817 
818     if (!c->no_fail_on_wrong_length && *error == GRIB_WRONG_LENGTH) {
819         grib_handle_delete(h);
820         h = NULL;
821     }
822 
823     return h;
824 }
825 
gts_new_from_file(grib_context * c,FILE * f,int * error)826 grib_handle* gts_new_from_file(grib_context* c, FILE* f, int* error)
827 {
828     void* data      = NULL;
829     size_t olen     = 0;
830     grib_handle* gl = NULL;
831     off_t offset    = 0;
832 
833     if (c == NULL)
834         c = grib_context_get_default();
835 
836     data = wmo_read_gts_from_file_malloc(f, 0, &olen, &offset, error);
837 
838     if (*error != GRIB_SUCCESS) {
839         if (data)
840             grib_context_free(c, data);
841 
842         if (*error == GRIB_END_OF_FILE)
843             *error = GRIB_SUCCESS;
844         return NULL;
845     }
846 
847     gl = grib_handle_new_from_message(c, data, olen);
848 
849     if (!gl) {
850         *error = GRIB_DECODING_ERROR;
851         grib_context_log(c, GRIB_LOG_ERROR, "gts_new_from_file: cannot create handle \n");
852         grib_context_free(c, data);
853         return NULL;
854     }
855 
856     gl->offset           = offset;
857     gl->buffer->property = GRIB_MY_BUFFER;
858     gl->product_kind     = PRODUCT_GTS;
859     grib_context_increment_handle_file_count(c);
860     grib_context_increment_handle_total_count(c);
861     if (gl->offset == 0)
862         grib_context_set_handle_file_count(c, 1);
863 
864     return gl;
865 }
866 
taf_new_from_file(grib_context * c,FILE * f,int * error)867 grib_handle* taf_new_from_file(grib_context* c, FILE* f, int* error)
868 {
869     void* data      = NULL;
870     size_t olen     = 0;
871     grib_handle* gl = NULL;
872     off_t offset    = 0;
873 
874     if (c == NULL)
875         c = grib_context_get_default();
876 
877     data = wmo_read_taf_from_file_malloc(f, 0, &olen, &offset, error);
878 
879     if (*error != GRIB_SUCCESS) {
880         if (data)
881             grib_context_free(c, data);
882 
883         if (*error == GRIB_END_OF_FILE)
884             *error = GRIB_SUCCESS;
885         return NULL;
886     }
887 
888     gl = grib_handle_new_from_message(c, data, olen);
889 
890     if (!gl) {
891         *error = GRIB_DECODING_ERROR;
892         grib_context_log(c, GRIB_LOG_ERROR, "taf_new_from_file: cannot create handle \n");
893         grib_context_free(c, data);
894         return NULL;
895     }
896 
897     gl->offset           = offset;
898     gl->buffer->property = GRIB_MY_BUFFER;
899     gl->product_kind     = PRODUCT_TAF;
900     grib_context_increment_handle_file_count(c);
901     grib_context_increment_handle_total_count(c);
902     if (gl->offset == 0)
903         grib_context_set_handle_file_count(c, 1);
904 
905     return gl;
906 }
907 
metar_new_from_file(grib_context * c,FILE * f,int * error)908 grib_handle* metar_new_from_file(grib_context* c, FILE* f, int* error)
909 {
910     void* data      = NULL;
911     size_t olen     = 0;
912     grib_handle* gl = NULL;
913     off_t offset    = 0;
914 
915     if (c == NULL)
916         c = grib_context_get_default();
917 
918     data = wmo_read_metar_from_file_malloc(f, 0, &olen, &offset, error);
919 
920     if (*error != GRIB_SUCCESS) {
921         if (data)
922             grib_context_free(c, data);
923 
924         if (*error == GRIB_END_OF_FILE)
925             *error = GRIB_SUCCESS;
926         return NULL;
927     }
928 
929     gl = grib_handle_new_from_message(c, data, olen);
930 
931     if (!gl) {
932         *error = GRIB_DECODING_ERROR;
933         grib_context_log(c, GRIB_LOG_ERROR, "metar_new_from_file: cannot create handle \n");
934         grib_context_free(c, data);
935         return NULL;
936     }
937 
938     gl->offset           = offset;
939     gl->buffer->property = GRIB_MY_BUFFER;
940     gl->product_kind     = PRODUCT_METAR;
941     grib_context_increment_handle_file_count(c);
942     grib_context_increment_handle_total_count(c);
943     if (gl->offset == 0)
944         grib_context_set_handle_file_count(c, 1);
945 
946     return gl;
947 }
948 
bufr_new_from_file(grib_context * c,FILE * f,int * error)949 grib_handle* bufr_new_from_file(grib_context* c, FILE* f, int* error)
950 {
951     void* data              = NULL;
952     size_t olen             = 0;
953     grib_handle* gl         = NULL;
954     off_t gts_header_offset = 0;
955     off_t offset = 0, end_msg_offset = 0;
956     char *gts_header = 0, *save_gts_header = 0;
957     int gtslen = 0;
958 
959     if (c == NULL)
960         c = grib_context_get_default();
961 
962     gts_header_offset = grib_context_tell(c, f);
963     data              = wmo_read_bufr_from_file_malloc(f, 0, &olen, &offset, error);
964     end_msg_offset    = grib_context_tell(c, f);
965 
966     if (*error != GRIB_SUCCESS) {
967         if (data)
968             grib_context_free(c, data);
969 
970         if (*error == GRIB_END_OF_FILE)
971             *error = GRIB_SUCCESS;
972         return NULL;
973     }
974 
975     if (c->gts_header_on) {
976         int g = 0;
977         grib_context_seek(c, gts_header_offset, SEEK_SET, f);
978         gtslen          = offset - gts_header_offset;
979         gts_header      = (char*)grib_context_malloc(c, sizeof(unsigned char) * gtslen);
980         save_gts_header = gts_header;
981         grib_context_read(c, gts_header, gtslen, f);
982         g = gtslen;
983         while (gts_header != NULL && g != 0 && *gts_header != '\03') {
984             /*printf("--------%d %X \n",gtslen,*gts_header);*/
985             gts_header++;
986             g--;
987         }
988         if (g > 8) {
989             gts_header++;
990             gtslen = g - 1;
991         }
992         else
993             gts_header = save_gts_header;
994         grib_context_seek(c, end_msg_offset, SEEK_SET, f);
995     }
996 
997     gl = grib_handle_new_from_message(c, data, olen);
998 
999     if (!gl) {
1000         *error = GRIB_DECODING_ERROR;
1001         grib_context_log(c, GRIB_LOG_ERROR, "bufr_new_from_file: cannot create handle \n");
1002         grib_context_free(c, data);
1003         return NULL;
1004     }
1005 
1006     gl->offset           = offset;
1007     gl->buffer->property = GRIB_MY_BUFFER;
1008     gl->product_kind     = PRODUCT_BUFR;
1009     grib_context_increment_handle_file_count(c);
1010     grib_context_increment_handle_total_count(c);
1011     if (gl->offset == 0)
1012         grib_context_set_handle_file_count(c, 1);
1013 
1014     if (c->gts_header_on && gtslen >= 8) {
1015         gl->gts_header = (char*)grib_context_malloc(c, sizeof(unsigned char) * gtslen);
1016         DebugAssert(gts_header);
1017         if (gts_header) memcpy(gl->gts_header, gts_header, gtslen);
1018         gl->gts_header_len = gtslen;
1019         grib_context_free(c, save_gts_header);
1020     }
1021     else {
1022         gl->gts_header = NULL;
1023     }
1024 
1025     return gl;
1026 }
1027 
any_new_from_file(grib_context * c,FILE * f,int * error)1028 grib_handle* any_new_from_file(grib_context* c, FILE* f, int* error)
1029 {
1030     void* data      = NULL;
1031     size_t olen     = 0;
1032     grib_handle* gl = NULL;
1033     off_t offset    = 0;
1034 
1035     if (c == NULL)
1036         c = grib_context_get_default();
1037 
1038     data = wmo_read_any_from_file_malloc(f, 0, &olen, &offset, error);
1039 
1040     if (*error != GRIB_SUCCESS) {
1041         if (data)
1042             grib_context_free(c, data);
1043 
1044         if (*error == GRIB_END_OF_FILE)
1045             *error = GRIB_SUCCESS;
1046         return NULL;
1047     }
1048 
1049     gl = grib_handle_new_from_message(c, data, olen);
1050 
1051     if (!gl) {
1052         *error = GRIB_DECODING_ERROR;
1053         grib_context_log(c, GRIB_LOG_ERROR, "any_new_from_file : cannot create handle\n");
1054         grib_context_free(c, data);
1055         return NULL;
1056     }
1057 
1058     gl->offset           = offset;
1059     gl->buffer->property = GRIB_MY_BUFFER;
1060     gl->product_kind     = PRODUCT_ANY;
1061     grib_context_increment_handle_file_count(c);
1062     grib_context_increment_handle_total_count(c);
1063     if (gl->offset == 0)
1064         grib_context_set_handle_file_count(c, 1);
1065 
1066     return gl;
1067 }
1068 
grib_handle_new_from_file_no_multi(grib_context * c,FILE * f,int headers_only,int * error)1069 static grib_handle* grib_handle_new_from_file_no_multi(grib_context* c, FILE* f, int headers_only, int* error)
1070 {
1071     void* data              = NULL;
1072     size_t olen             = 0;
1073     grib_handle* gl         = NULL;
1074     off_t gts_header_offset = 0;
1075     off_t offset = 0, end_msg_offset = 0;
1076     char *gts_header = 0, *save_gts_header = 0;
1077     int gtslen = 0;
1078 
1079     if (c == NULL)
1080         c = grib_context_get_default();
1081 
1082     gts_header_offset = grib_context_tell(c, f);
1083     data              = wmo_read_grib_from_file_malloc(f, headers_only, &olen, &offset, error);
1084     end_msg_offset    = grib_context_tell(c, f);
1085 
1086     if (*error != GRIB_SUCCESS) {
1087         if (data)
1088             grib_context_free(c, data);
1089 
1090         if (*error == GRIB_END_OF_FILE)
1091             *error = GRIB_SUCCESS;
1092         return NULL;
1093     }
1094 
1095     if (c->gts_header_on) {
1096         int g = 0;
1097         grib_context_seek(c, gts_header_offset, SEEK_SET, f);
1098         gtslen          = offset - gts_header_offset;
1099         gts_header      = (char*)grib_context_malloc(c, sizeof(unsigned char) * gtslen);
1100         save_gts_header = gts_header;
1101         grib_context_read(c, gts_header, gtslen, f);
1102         g = gtslen;
1103         while (gts_header != NULL && g != 0 && *gts_header != '\03') {
1104             /*printf("--------%d %X \n",gtslen,*gts_header);*/
1105             gts_header++;
1106             g--;
1107         }
1108         if (g > 8) {
1109             gts_header++;
1110             gtslen = g - 1;
1111         }
1112         else
1113             gts_header = save_gts_header;
1114         grib_context_seek(c, end_msg_offset, SEEK_SET, f);
1115     }
1116 
1117     if (headers_only) {
1118         gl = grib_handle_new_from_partial_message(c, data, olen);
1119     }
1120     else {
1121         gl = grib_handle_new_from_message(c, data, olen);
1122     }
1123 
1124     if (!gl) {
1125         *error = GRIB_DECODING_ERROR;
1126         grib_context_log(c, GRIB_LOG_ERROR, "grib_handle_new_from_file_no_multi: cannot create handle\n");
1127         grib_context_free(c, data);
1128         return NULL;
1129     }
1130 
1131     gl->offset           = offset;
1132     gl->buffer->property = GRIB_MY_BUFFER;
1133 
1134     grib_context_increment_handle_file_count(c);
1135     grib_context_increment_handle_total_count(c);
1136 
1137     if (c->gts_header_on && gtslen >= 8) {
1138         gl->gts_header = (char*)grib_context_malloc(c, sizeof(unsigned char) * gtslen);
1139         DebugAssert(gts_header);
1140         if (gts_header) memcpy(gl->gts_header, gts_header, gtslen);
1141         gl->gts_header_len = gtslen;
1142         grib_context_free(c, save_gts_header);
1143     }
1144     else {
1145         gl->gts_header = NULL;
1146     }
1147 
1148     return gl;
1149 }
1150 
grib_multi_handle_new(grib_context * c)1151 grib_multi_handle* grib_multi_handle_new(grib_context* c)
1152 {
1153     grib_multi_handle* h;
1154     if (c == NULL)
1155         c = grib_context_get_default();
1156     if (!c->multi_support_on) {
1157         grib_context_log(c, GRIB_LOG_DEBUG, "grib_multi_handle_new: Setting multi_support_on = 1");
1158         c->multi_support_on = 1;
1159     }
1160     h = (grib_multi_handle*)grib_context_malloc_clear(c, sizeof(grib_multi_handle));
1161     if (h == NULL) {
1162         grib_context_log(c, GRIB_LOG_ERROR,
1163                          "grib_multi_handle_new: unable to allocate memory. %s",
1164                          grib_get_error_message(GRIB_OUT_OF_MEMORY));
1165         return NULL;
1166     }
1167     h->buffer          = grib_create_growable_buffer(c);
1168     h->buffer->ulength = 0;
1169     h->context         = c;
1170 
1171     return h;
1172 }
1173 
grib_multi_handle_delete(grib_multi_handle * h)1174 int grib_multi_handle_delete(grib_multi_handle* h)
1175 {
1176     if (h == NULL)
1177         return GRIB_SUCCESS;
1178 
1179     grib_buffer_delete(h->context, h->buffer);
1180     grib_context_free(h->context, h);
1181     return GRIB_SUCCESS;
1182 }
1183 
grib_multi_handle_append(grib_handle * h,int start_section,grib_multi_handle * mh)1184 int grib_multi_handle_append(grib_handle* h, int start_section, grib_multi_handle* mh)
1185 {
1186     const void* mess = NULL;
1187     unsigned char* p = NULL;
1188     int err          = 0;
1189     size_t mess_len  = 0;
1190     size_t total_len = 0;
1191 
1192     if (!h)
1193         return GRIB_NULL_HANDLE;
1194     if (!mh)
1195         return GRIB_NULL_HANDLE;
1196 
1197     if (start_section == 0 || mh->buffer->ulength == 0) {
1198         err = grib_get_message(h, &mess, &mess_len);
1199         if (err != 0)
1200             return err;
1201         total_len = mh->buffer->ulength + mess_len;
1202 
1203         if (total_len > mh->buffer->length)
1204             grib_grow_buffer(h->context, mh->buffer, total_len);
1205 
1206         p = mh->buffer->data + mh->buffer->ulength;
1207         memcpy(p, mess, mess_len);
1208         mh->offset          = mh->buffer->ulength;
1209         mh->buffer->ulength = total_len;
1210         mh->length          = mess_len;
1211     }
1212     else {
1213         long off = 0;
1214         err      = grib_get_partial_message(h, &mess, &mess_len, start_section);
1215         if (err != 0)
1216             return err;
1217         total_len = mh->buffer->ulength + mess_len - 4;
1218 
1219         while (total_len > mh->buffer->length)
1220             grib_grow_buffer(h->context, mh->buffer, total_len);
1221 
1222         p = mh->buffer->data + mh->buffer->ulength - 4;
1223         memcpy(p, mess, mess_len);
1224         mh->length += mess_len - 4;
1225 
1226         off = mh->offset + 64;
1227 
1228         grib_encode_unsigned_long(mh->buffer->data, mh->length, &off, 64);
1229         mh->buffer->ulength = total_len;
1230     }
1231     return err;
1232 }
1233 
grib_multi_handle_write(grib_multi_handle * h,FILE * f)1234 int grib_multi_handle_write(grib_multi_handle* h, FILE* f)
1235 {
1236     if (f == NULL)
1237         return GRIB_INVALID_FILE;
1238     if (h == NULL)
1239         return GRIB_INVALID_GRIB;
1240 
1241     if (fwrite(h->buffer->data, 1, h->buffer->ulength, f) != h->buffer->ulength) {
1242         grib_context_log(h->context, GRIB_LOG_PERROR, "grib_multi_handle_write writing on file");
1243         return GRIB_IO_PROBLEM;
1244     }
1245 
1246     return 0;
1247 }
1248 
grib_get_partial_message(grib_handle * h,const void ** msg,size_t * len,int start_section)1249 int grib_get_partial_message(grib_handle* h, const void** msg, size_t* len, int start_section)
1250 {
1251     size_t partial_len  = 0;
1252     long section_offset = 0;
1253     if (!h)
1254         return GRIB_NULL_HANDLE;
1255 
1256     if (start_section > h->sections_count)
1257         return GRIB_INVALID_SECTION_NUMBER;
1258 
1259     grib_get_long(h, h->section_offset[start_section], &section_offset);
1260     partial_len = h->buffer->ulength - section_offset;
1261 
1262     *len = partial_len;
1263     *msg = h->buffer->data + section_offset;
1264 
1265     return GRIB_SUCCESS;
1266 }
1267 
grib_get_partial_message_copy(grib_handle * h,void * message,size_t * len,int start_section)1268 int grib_get_partial_message_copy(grib_handle* h, void* message, size_t* len,
1269                                   int start_section)
1270 {
1271     size_t partial_len  = 0;
1272     long section_offset = 0;
1273     if (!h)
1274         return GRIB_NULL_HANDLE;
1275 
1276     if (start_section > h->sections_count)
1277         return GRIB_INVALID_SECTION_NUMBER;
1278 
1279     grib_get_long(h, h->section_offset[start_section], &section_offset);
1280     partial_len = h->buffer->ulength - section_offset;
1281 
1282     if (*len < partial_len)
1283         return GRIB_BUFFER_TOO_SMALL;
1284 
1285     *len = partial_len;
1286 
1287     memcpy(message, h->buffer->data + section_offset, *len);
1288     return GRIB_SUCCESS;
1289 }
1290 
grib_get_message_copy(const grib_handle * h,void * message,size_t * len)1291 int grib_get_message_copy(const grib_handle* h, void* message, size_t* len)
1292 {
1293     if (!h)
1294         return GRIB_NOT_FOUND;
1295 
1296     if (*len < h->buffer->ulength)
1297         return GRIB_BUFFER_TOO_SMALL;
1298 
1299     *len = h->buffer->ulength;
1300 
1301     memcpy(message, h->buffer->data, *len);
1302     return GRIB_SUCCESS;
1303 }
1304 
grib_get_message_offset(const grib_handle * h,off_t * offset)1305 int grib_get_message_offset(const grib_handle* h, off_t* offset)
1306 {
1307     if (h)
1308         *offset = h->offset;
1309     else
1310         return GRIB_INTERNAL_ERROR;
1311 
1312     return 0;
1313 }
1314 
codes_get_product_kind(const grib_handle * h,ProductKind * product_kind)1315 int codes_get_product_kind(const grib_handle* h, ProductKind* product_kind)
1316 {
1317     if (h) {
1318         *product_kind = h->product_kind;
1319         return GRIB_SUCCESS;
1320     }
1321     return GRIB_NULL_HANDLE;
1322 }
1323 
codes_check_message_header(const void * bytes,size_t length,ProductKind product)1324 int codes_check_message_header(const void* bytes, size_t length, ProductKind product)
1325 {
1326     const char* p = ((const char*)bytes);
1327     Assert(p);
1328     Assert(product == PRODUCT_GRIB || product == PRODUCT_BUFR); /* Others not yet implemented */
1329     Assert(length > 4);
1330     if (product == PRODUCT_GRIB) {
1331         if (p[0] != 'G' || p[1] != 'R' || p[2] != 'I' || p[3] != 'B')
1332             return GRIB_INVALID_MESSAGE;
1333     }
1334     else if (product == PRODUCT_BUFR) {
1335         if (p[0] != 'B' || p[1] != 'U' || p[2] != 'F' || p[3] != 'R')
1336             return GRIB_INVALID_MESSAGE;
1337     }
1338     else {
1339         return GRIB_NOT_IMPLEMENTED;
1340     }
1341 
1342     return GRIB_SUCCESS;
1343 }
codes_check_message_footer(const void * bytes,size_t length,ProductKind product)1344 int codes_check_message_footer(const void* bytes, size_t length, ProductKind product)
1345 {
1346     const char* p = ((const char*)bytes);
1347     Assert(p);
1348     Assert(product == PRODUCT_GRIB || product == PRODUCT_BUFR); /* Others not yet implemented */
1349 
1350     if (p[length - 4] != '7' || p[length - 3] != '7' || p[length - 2] != '7' || p[length - 1] != '7') {
1351         return GRIB_7777_NOT_FOUND;
1352     }
1353     return GRIB_SUCCESS;
1354 }
1355 
grib_get_message_size(const grib_handle * ch,size_t * size)1356 int grib_get_message_size(const grib_handle* ch, size_t* size)
1357 {
1358     long totalLength = 0;
1359     int ret          = 0;
1360     grib_handle* h   = (grib_handle*)ch;
1361     *size            = h->buffer->ulength;
1362     ret              = grib_get_long(h, "totalLength", &totalLength);
1363     if (!ret)
1364         *size = totalLength;
1365     return ret;
1366 }
1367 
grib_get_message(const grib_handle * ch,const void ** msg,size_t * size)1368 int grib_get_message(const grib_handle* ch, const void** msg, size_t* size)
1369 {
1370     long totalLength = 0;
1371     int ret          = 0;
1372     grib_handle* h   = (grib_handle*)ch;
1373     *msg             = h->buffer->data;
1374     *size            = h->buffer->ulength;
1375 
1376     ret = grib_get_long(h, "totalLength", &totalLength);
1377     if (!ret)
1378         *size = totalLength;
1379 
1380     if (h->context->gts_header_on && h->gts_header) {
1381         char strbuf[10];
1382         sprintf(strbuf, "%.8d", (int)(h->buffer->ulength + h->gts_header_len - 6));
1383         memcpy(h->gts_header, strbuf, 8);
1384     }
1385     return 0;
1386 }
1387 
grib_get_message_headers(grib_handle * h,const void ** msg,size_t * size)1388 int grib_get_message_headers(grib_handle* h, const void** msg, size_t* size)
1389 {
1390     int ret = 0;
1391     size_t endOfHeadersMarker;
1392     *msg  = h->buffer->data;
1393     *size = h->buffer->ulength;
1394 
1395     if ((ret = grib_get_offset(h, "endOfHeadersMarker", &endOfHeadersMarker)) != GRIB_SUCCESS) {
1396         grib_context_log(h->context, GRIB_LOG_FATAL,
1397                          "grib_get_message_headers unable to get offset of endOfHeadersMarker");
1398         return ret;
1399     }
1400 
1401     *size = endOfHeadersMarker;
1402 
1403     return ret;
1404 }
1405 
grib_handle_new(grib_context * c)1406 grib_handle* grib_handle_new(grib_context* c)
1407 {
1408     grib_handle* h;
1409 
1410     if (!c)
1411         c = grib_context_get_default();
1412     h         = grib_new_handle(c);
1413     h->buffer = grib_create_growable_buffer(c);
1414     if (h->buffer == NULL) {
1415         grib_handle_delete(h);
1416         return NULL;
1417     }
1418     h->root = grib_create_root_section(h->context, h);
1419 
1420     if (!h->root) {
1421         grib_context_log(c, GRIB_LOG_ERROR, "grib_handle_new: cannot create root section");
1422         grib_handle_delete(h);
1423         return NULL;
1424     }
1425 
1426     if (!h->context->grib_reader || !h->context->grib_reader->first) {
1427         grib_context_log(c, GRIB_LOG_ERROR, "grib_handle_new: cannot create handle, no definitions found");
1428         grib_handle_delete(h);
1429         return NULL;
1430     }
1431 
1432     h->buffer->property = GRIB_USER_BUFFER;
1433 
1434     h->header_mode = 1;
1435 
1436     return h;
1437 }
1438 
grib_action_from_filter(const char * filter)1439 grib_action* grib_action_from_filter(const char* filter)
1440 {
1441     grib_action* a        = NULL;
1442     grib_context* context = grib_context_get_default();
1443     a                     = grib_parse_file(context, filter);
1444 
1445     if (context->grib_reader && context->grib_reader->first) {
1446         grib_context_free_persistent(context, context->grib_reader->first->filename);
1447         grib_context_free_persistent(context, context->grib_reader->first);
1448         grib_context_free_persistent(context, context->grib_reader);
1449     }
1450 
1451     context->grib_reader = NULL;
1452     return a;
1453 }
1454 
grib_handle_apply_action(grib_handle * h,grib_action * a)1455 int grib_handle_apply_action(grib_handle* h, grib_action* a)
1456 {
1457     int err;
1458 
1459     if (!a)
1460         return GRIB_SUCCESS; /* TODO: return error */
1461 
1462     while (a) {
1463         err = grib_action_execute(a, h);
1464         if (err != GRIB_SUCCESS)
1465             return err;
1466         a = a->next;
1467     }
1468 
1469     return GRIB_SUCCESS;
1470 }
1471 
grib_handle_prepare_action(grib_handle * h,grib_action * a)1472 int grib_handle_prepare_action(grib_handle* h, grib_action* a)
1473 {
1474     int err;
1475 
1476     if (!a)
1477         return GRIB_SUCCESS; /* TODO: return error */
1478 
1479     while (a) {
1480         err = grib_action_execute(a, h);
1481         if (err != GRIB_SUCCESS)
1482             return err;
1483         a = a->next;
1484     }
1485 
1486     return GRIB_SUCCESS;
1487 }
1488 
grib2_get_next_section(unsigned char * msgbegin,size_t msglen,unsigned char ** secbegin,size_t * seclen,int * secnum,int * err)1489 static int grib2_get_next_section(unsigned char* msgbegin, size_t msglen, unsigned char** secbegin, size_t* seclen, int* secnum, int* err)
1490 {
1491     if (!grib2_has_next_section(msgbegin, msglen, *secbegin, *seclen, err))
1492         return 0;
1493 
1494     *secbegin += *seclen;
1495     *seclen = grib_decode_unsigned_byte_long(*secbegin, 0, 4);
1496     *secnum = grib_decode_unsigned_byte_long(*secbegin, 4, 1);
1497 
1498     if (*secnum < 1 || *secnum > 7) {
1499         *err = GRIB_INVALID_SECTION_NUMBER;
1500         return 0;
1501     }
1502     return 1;
1503 }
1504 
grib2_has_next_section(unsigned char * msgbegin,size_t msglen,unsigned char * secbegin,size_t seclen,int * err)1505 static int grib2_has_next_section(unsigned char* msgbegin, size_t msglen, unsigned char* secbegin, size_t seclen, int* err)
1506 {
1507     long next_seclen;
1508     *err = 0;
1509 
1510     next_seclen = (msgbegin + msglen) - (secbegin + seclen);
1511 
1512     if (next_seclen < 5) {
1513         if ((next_seclen > 3) && !strncmp((char*)secbegin, "7777", 4))
1514             *err = GRIB_SUCCESS;
1515         else
1516             *err = GRIB_7777_NOT_FOUND;
1517         return 0;
1518     }
1519 
1520     /*secbegin += seclen;*/
1521 
1522     return 1;
1523 }
1524 
grib2_build_message(grib_context * context,unsigned char * sections[],size_t sections_len[],void ** data,size_t * len)1525 static void grib2_build_message(grib_context* context, unsigned char* sections[], size_t sections_len[], void** data, size_t* len)
1526 {
1527     int i            = 0;
1528     char* theEnd     = "7777";
1529     unsigned char* p = 0;
1530     size_t msglen    = 0;
1531     long bitp        = 64;
1532     if (!sections[0]) {
1533         *data = NULL;
1534         return;
1535     }
1536 
1537     for (i = 0; i < 8; i++)
1538         msglen += sections_len[i];
1539     msglen += 4;
1540     if (*len < msglen)
1541         msglen = *len;
1542 
1543     *data = (unsigned char*)grib_context_malloc(context, msglen);
1544     p     = (unsigned char*)*data;
1545 
1546     for (i = 0; i < 8; i++) {
1547         if (sections[i]) {
1548             memcpy(p, sections[i], sections_len[i]);
1549             p += sections_len[i];
1550         }
1551     }
1552 
1553     memcpy(p, theEnd, 4);
1554 
1555     grib_encode_unsigned_long((unsigned char*)*data, msglen, &bitp, 64);
1556 
1557     *len = msglen;
1558 }
1559 
1560 /* For multi support mode: Reset all file handles equal to f. See GRIB-249 */
grib_multi_support_reset_file(grib_context * c,FILE * f)1561 void grib_multi_support_reset_file(grib_context* c, FILE* f)
1562 {
1563     grib_multi_support* gm = NULL;
1564     if (!c)
1565         c = grib_context_get_default();
1566     gm = c->multi_support;
1567     while (gm) {
1568         if (gm->file == f) {
1569             gm->file = NULL;
1570         }
1571         gm = gm->next;
1572     }
1573 }
1574 
grib_get_multi_support(grib_context * c,FILE * f)1575 static grib_multi_support* grib_get_multi_support(grib_context* c, FILE* f)
1576 {
1577     int i                    = 0;
1578     grib_multi_support* gm   = c->multi_support;
1579     grib_multi_support* prev = NULL;
1580 
1581     while (gm) {
1582         if (gm->file == f)
1583             return gm;
1584         prev = gm;
1585         gm   = gm->next;
1586     }
1587 
1588     if (!gm) {
1589         gm = grib_multi_support_new(c);
1590         if (!c->multi_support) {
1591             c->multi_support = gm;
1592         }
1593         else {
1594             if (prev)
1595                 prev->next = gm;
1596         }
1597     }
1598 
1599     gm->next = 0;
1600     if (gm->message)
1601         grib_context_free(c, gm->message);
1602     gm->message            = NULL;
1603     gm->section_number     = 0;
1604     gm->sections_length[0] = 16;
1605     for (i = 1; i < 8; i++)
1606         gm->sections_length[i] = 0;
1607     gm->sections_length[8] = 4;
1608     gm->file               = f;
1609 
1610     return gm;
1611 }
1612 
grib_multi_support_reset(grib_context * c)1613 void grib_multi_support_reset(grib_context* c)
1614 {
1615     grib_multi_support* gm   = c->multi_support;
1616     grib_multi_support* next = NULL;
1617     int i                    = 0;
1618     while (next) {
1619         next = gm->next;
1620         if (gm->file)
1621             fclose(gm->file);
1622         if (gm->message)
1623             grib_context_free(c, gm->message);
1624         gm->message = NULL;
1625         for (i = 0; i < 8; i++)
1626             gm->sections[i] = 0;
1627         if (gm->bitmap_section)
1628             grib_context_free(c, gm->bitmap_section);
1629         gm->bitmap_section = NULL;
1630         grib_context_free(c, gm);
1631         gm = NULL;
1632     }
1633 }
1634 
grib_multi_support_new(grib_context * c)1635 static grib_multi_support* grib_multi_support_new(grib_context* c)
1636 {
1637     int i = 0;
1638     grib_multi_support* gm =
1639         (grib_multi_support*)grib_context_malloc_clear(c, sizeof(grib_multi_support));
1640     gm->file                  = NULL;
1641     gm->message               = NULL;
1642     gm->message_length        = 0;
1643     gm->bitmap_section        = NULL;
1644     gm->bitmap_section_length = 0;
1645     gm->section_number        = 0;
1646     gm->next                  = 0;
1647     gm->sections_length[0]    = 16;
1648     for (i = 1; i < 8; i++)
1649         gm->sections_length[i] = 0;
1650     gm->sections_length[8] = 4;
1651 
1652     return gm;
1653 }
1654