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], §ion_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], §ion_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