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 #include "grib_api_internal.h"
12 #include "assert.h"
13 
14 #if HAVE_SYS_TYPES_H
15 #include <sys/types.h>
16 #endif
17 
18 #if HAVE_SYS_STAT_H
19 #include <sys/stat.h>
20 #endif
21 
22 #ifdef HAVE_FCNTL_H
23 #include <fcntl.h>
24 #endif
25 
26 #include <ctype.h>
27 #include <errno.h>
28 
29 #if GRIB_PTHREADS
30 static pthread_once_t once                 = PTHREAD_ONCE_INIT;
31 static pthread_mutex_t handle_mutex        = PTHREAD_MUTEX_INITIALIZER;
32 static pthread_mutex_t index_mutex         = PTHREAD_MUTEX_INITIALIZER;
33 static pthread_mutex_t multi_handle_mutex  = PTHREAD_MUTEX_INITIALIZER;
34 static pthread_mutex_t iterator_mutex      = PTHREAD_MUTEX_INITIALIZER;
35 static pthread_mutex_t keys_iterator_mutex = PTHREAD_MUTEX_INITIALIZER;
36 
init()37 static void init()
38 {
39     pthread_mutexattr_t attr;
40 
41     pthread_mutexattr_init(&attr);
42     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
43     pthread_mutex_init(&handle_mutex, &attr);
44     pthread_mutex_init(&index_mutex, &attr);
45     pthread_mutex_init(&multi_handle_mutex, &attr);
46     pthread_mutex_init(&iterator_mutex, &attr);
47     pthread_mutex_init(&keys_iterator_mutex, &attr);
48     pthread_mutexattr_destroy(&attr);
49 }
50 #elif GRIB_OMP_THREADS
51 static int once = 0;
52 static omp_nest_lock_t handle_mutex;
53 static omp_nest_lock_t index_mutex;
54 static omp_nest_lock_t multi_handle_mutex;
55 static omp_nest_lock_t iterator_mutex;
56 static omp_nest_lock_t keys_iterator_mutex;
57 
init()58 static void init()
59 {
60     GRIB_OMP_CRITICAL(lock_python)
61     {
62         if (once == 0) {
63             omp_init_nest_lock(&handle_mutex);
64             omp_init_nest_lock(&index_mutex);
65             omp_init_nest_lock(&multi_handle_mutex);
66             omp_init_nest_lock(&iterator_mutex);
67             omp_init_nest_lock(&keys_iterator_mutex);
68             once = 1;
69         }
70     }
71 }
72 #endif
73 
74 int GRIB_NULL         = -1;
75 int GRIB_NULL_NEAREST = -1;
76 
77 typedef struct l_grib_file l_grib_file;
78 
79 struct l_grib_file
80 {
81     int id;
82     FILE* f;
83     l_grib_file* next;
84 };
85 
86 typedef struct l_grib_handle l_grib_handle;
87 
88 struct l_grib_handle
89 {
90     int id;
91     grib_handle* h;
92     l_grib_handle* next;
93 };
94 
95 typedef struct l_grib_index l_grib_index;
96 
97 struct l_grib_index
98 {
99     int id;
100     grib_index* h;
101     l_grib_index* next;
102 };
103 
104 typedef struct l_grib_multi_handle l_grib_multi_handle;
105 
106 struct l_grib_multi_handle
107 {
108     int id;
109     grib_multi_handle* h;
110     l_grib_multi_handle* next;
111 };
112 
113 typedef struct l_grib_iterator l_grib_iterator;
114 
115 struct l_grib_iterator
116 {
117     int id;
118     grib_iterator* i;
119     l_grib_iterator* next;
120 };
121 
122 typedef struct l_grib_keys_iterator l_grib_keys_iterator;
123 struct l_grib_keys_iterator
124 {
125     int id;
126     grib_keys_iterator* i;
127     l_grib_keys_iterator* next;
128 };
129 
130 typedef struct l_bufr_keys_iterator l_bufr_keys_iterator;
131 struct l_bufr_keys_iterator
132 {
133     int id;
134     bufr_keys_iterator* i;
135     l_bufr_keys_iterator* next;
136 };
137 
138 static l_grib_handle* handle_set                    = NULL;
139 static l_grib_index* index_set                      = NULL;
140 static l_grib_multi_handle* multi_handle_set        = NULL;
141 static l_grib_file* file_set                        = NULL;
142 static l_grib_iterator* iterator_set                = NULL;
143 static l_grib_keys_iterator* keys_iterator_set      = NULL;
144 static l_bufr_keys_iterator* bufr_keys_iterator_set = NULL;
145 
push_file(FILE * f)146 static int push_file(FILE* f)
147 {
148     l_grib_file* current  = file_set;
149     l_grib_file* previous = file_set;
150     l_grib_file* new      = NULL;
151     int myindex           = 1;
152 
153     if (!file_set) {
154         file_set       = malloc(sizeof(l_grib_file));
155         file_set->id   = myindex;
156         file_set->f    = f;
157         file_set->next = NULL;
158         return myindex;
159     }
160 
161     while (current) {
162         if (current->id < 0) {
163             current->id = -(current->id);
164             current->f  = f;
165             return current->id;
166         }
167         else {
168             myindex++;
169             previous = current;
170             current  = current->next;
171         }
172     }
173 
174     new            = malloc(sizeof(l_grib_file));
175     new->id        = myindex;
176     new->f         = f;
177     new->next      = current;
178     previous->next = new;
179     return myindex;
180 }
181 
_push_handle(grib_handle * h,int * gid)182 static void _push_handle(grib_handle* h, int* gid)
183 {
184     l_grib_handle* current  = handle_set;
185     l_grib_handle* previous = handle_set;
186     l_grib_handle* new      = NULL;
187     int myindex             = 1;
188 
189     if (*gid > 0) {
190         while (current) {
191             if (current->id == *gid) break;
192             current = current->next;
193         }
194         if (current) {
195             grib_handle_delete(current->h);
196             current->h = h;
197             return;
198         }
199     }
200 
201     current = handle_set;
202 
203     if (!handle_set) {
204         handle_set       = malloc(sizeof(l_grib_handle));
205         handle_set->id   = myindex;
206         handle_set->h    = h;
207         handle_set->next = NULL;
208         *gid             = myindex;
209         return;
210     }
211 
212     while (current) {
213         if (current->id < 0) {
214             current->id = -(current->id);
215             current->h  = h;
216             *gid        = current->id;
217             return;
218         }
219         else {
220             myindex++;
221             previous = current;
222             current  = current->next;
223         }
224     }
225 
226     new            = malloc(sizeof(l_grib_handle));
227     new->id        = myindex;
228     new->h         = h;
229     new->next      = current;
230     previous->next = new;
231 
232     *gid = myindex;
233     return;
234 }
235 
_push_index(grib_index * h,int * gid)236 static void _push_index(grib_index* h, int* gid)
237 {
238     l_grib_index* current  = index_set;
239     l_grib_index* previous = index_set;
240     l_grib_index* new      = NULL;
241     int myindex            = 1;
242 
243     if (*gid > 0) {
244         while (current) {
245             if (current->id == *gid) break;
246             current = current->next;
247         }
248         if (current) {
249             grib_index_delete(current->h);
250             current->h = h;
251             return;
252         }
253     }
254 
255     current = index_set;
256 
257     if (!index_set) {
258         index_set       = malloc(sizeof(l_grib_index));
259         index_set->id   = myindex;
260         index_set->h    = h;
261         index_set->next = NULL;
262         *gid            = myindex;
263         return;
264     }
265 
266     while (current) {
267         if (current->id < 0) {
268             current->id = -(current->id);
269             current->h  = h;
270             *gid        = current->id;
271             return;
272         }
273         else {
274             myindex++;
275             previous = current;
276             current  = current->next;
277         }
278     }
279 
280     new            = malloc(sizeof(l_grib_index));
281     new->id        = myindex;
282     new->h         = h;
283     new->next      = current;
284     previous->next = new;
285 
286     *gid = myindex;
287     return;
288 }
289 
_push_multi_handle(grib_multi_handle * h,int * gid)290 static void _push_multi_handle(grib_multi_handle* h, int* gid)
291 {
292     l_grib_multi_handle* current  = multi_handle_set;
293     l_grib_multi_handle* previous = multi_handle_set;
294     l_grib_multi_handle* new      = NULL;
295     int myindex                   = 1;
296 
297     if (*gid > 0) {
298         while (current) {
299             if (current->id == *gid) break;
300             current = current->next;
301         }
302         if (current) {
303             grib_multi_handle_delete(current->h);
304             current->h = h;
305             return;
306         }
307     }
308 
309     current = multi_handle_set;
310 
311     if (!multi_handle_set) {
312         multi_handle_set       = malloc(sizeof(l_grib_multi_handle));
313         multi_handle_set->id   = myindex;
314         multi_handle_set->h    = h;
315         multi_handle_set->next = NULL;
316         *gid                   = myindex;
317         return;
318     }
319 
320     while (current) {
321         if (current->id < 0) {
322             current->id = -(current->id);
323             current->h  = h;
324             *gid        = current->id;
325             return;
326         }
327         else {
328             myindex++;
329             previous = current;
330             current  = current->next;
331         }
332     }
333 
334     new            = malloc(sizeof(l_grib_multi_handle));
335     new->id        = myindex;
336     new->h         = h;
337     new->next      = current;
338     previous->next = new;
339 
340     *gid = myindex;
341     return;
342 }
343 
push_handle(grib_handle * h,int * gid)344 static void push_handle(grib_handle* h, int* gid)
345 {
346     GRIB_MUTEX_INIT_ONCE(&once, &init)
347     GRIB_MUTEX_LOCK(&handle_mutex)
348     _push_handle(h, gid);
349     GRIB_MUTEX_UNLOCK(&handle_mutex)
350     return;
351 }
352 
push_index(grib_index * h,int * gid)353 static void push_index(grib_index* h, int* gid)
354 {
355     GRIB_MUTEX_INIT_ONCE(&once, &init)
356     GRIB_MUTEX_LOCK(&index_mutex)
357     _push_index(h, gid);
358     GRIB_MUTEX_UNLOCK(&index_mutex)
359     return;
360 }
361 
push_multi_handle(grib_multi_handle * h,int * gid)362 static void push_multi_handle(grib_multi_handle* h, int* gid)
363 {
364     GRIB_MUTEX_INIT_ONCE(&once, &init)
365     GRIB_MUTEX_LOCK(&multi_handle_mutex)
366     _push_multi_handle(h, gid);
367     GRIB_MUTEX_UNLOCK(&multi_handle_mutex)
368     return;
369 }
370 
_push_iterator(grib_iterator * i)371 static int _push_iterator(grib_iterator* i)
372 {
373     l_grib_iterator* current  = iterator_set;
374     l_grib_iterator* previous = iterator_set;
375     l_grib_iterator* new      = NULL;
376     int myindex               = 1;
377 
378     if (!iterator_set) {
379         iterator_set       = malloc(sizeof(l_grib_iterator));
380         iterator_set->id   = myindex;
381         iterator_set->i    = i;
382         iterator_set->next = NULL;
383         return myindex;
384     }
385 
386     while (current) {
387         if (current->id < 0) {
388             current->id = -(current->id);
389             current->i  = i;
390             return current->id;
391         }
392         else {
393             myindex++;
394             previous = current;
395             current  = current->next;
396         }
397     }
398 
399     new            = malloc(sizeof(l_grib_iterator));
400     new->id        = myindex;
401     new->i         = i;
402     new->next      = current;
403     previous->next = new;
404 
405     return myindex;
406 }
407 
push_iterator(grib_iterator * i)408 static int push_iterator(grib_iterator* i)
409 {
410     int ret = 0;
411     GRIB_MUTEX_INIT_ONCE(&once, &init)
412     GRIB_MUTEX_LOCK(&iterator_mutex)
413     ret = _push_iterator(i);
414     GRIB_MUTEX_UNLOCK(&iterator_mutex)
415     return ret;
416 }
417 
_push_keys_iterator(grib_keys_iterator * i)418 static int _push_keys_iterator(grib_keys_iterator* i)
419 {
420     l_grib_keys_iterator* current  = keys_iterator_set;
421     l_grib_keys_iterator* previous = keys_iterator_set;
422     l_grib_keys_iterator* new      = NULL;
423     int myindex                    = 1;
424 
425     if (!keys_iterator_set) {
426         keys_iterator_set       = malloc(sizeof(l_grib_keys_iterator));
427         keys_iterator_set->id   = myindex;
428         keys_iterator_set->i    = i;
429         keys_iterator_set->next = NULL;
430         return myindex;
431     }
432 
433     while (current) {
434         if (current->id < 0) {
435             current->id = -(current->id);
436             current->i  = i;
437             return current->id;
438         }
439         else {
440             myindex++;
441             previous = current;
442             current  = current->next;
443         }
444     }
445     if (!previous) return -1;
446 
447     new            = malloc(sizeof(l_grib_keys_iterator));
448     new->id        = myindex;
449     new->i         = i;
450     new->next      = current;
451     previous->next = new;
452 
453     return myindex;
454 }
push_keys_iterator(grib_keys_iterator * i)455 static int push_keys_iterator(grib_keys_iterator* i)
456 {
457     int ret = 0;
458     GRIB_MUTEX_INIT_ONCE(&once, &init)
459     GRIB_MUTEX_LOCK(&keys_iterator_mutex)
460     ret = _push_keys_iterator(i);
461     GRIB_MUTEX_UNLOCK(&keys_iterator_mutex)
462     return ret;
463 }
464 
465 //BUFR keys iterator
_push_bufr_keys_iterator(bufr_keys_iterator * i)466 static int _push_bufr_keys_iterator(bufr_keys_iterator* i)
467 {
468     l_bufr_keys_iterator* current  = bufr_keys_iterator_set;
469     l_bufr_keys_iterator* previous = bufr_keys_iterator_set;
470     l_bufr_keys_iterator* the_new  = NULL;
471     int myindex                    = 1;
472 
473     if (!bufr_keys_iterator_set) {
474         bufr_keys_iterator_set = (l_bufr_keys_iterator*)malloc(sizeof(l_bufr_keys_iterator));
475         Assert(bufr_keys_iterator_set);
476         bufr_keys_iterator_set->id   = myindex;
477         bufr_keys_iterator_set->i    = i;
478         bufr_keys_iterator_set->next = NULL;
479         return myindex;
480     }
481 
482     while (current) {
483         if (current->id < 0) {
484             current->id = -(current->id);
485             current->i  = i;
486             return current->id;
487         }
488         else {
489             myindex++;
490             previous = current;
491             current  = current->next;
492         }
493     }
494     if (!previous) return -1;
495 
496     the_new = (l_bufr_keys_iterator*)malloc(sizeof(l_bufr_keys_iterator));
497     Assert(the_new);
498     the_new->id    = myindex;
499     the_new->i     = i;
500     the_new->next  = current;
501     previous->next = the_new;
502 
503     return myindex;
504 }
push_bufr_keys_iterator(bufr_keys_iterator * i)505 static int push_bufr_keys_iterator(bufr_keys_iterator* i)
506 {
507     int ret = 0;
508     GRIB_MUTEX_INIT_ONCE(&once, &init);
509     GRIB_MUTEX_LOCK(&keys_iterator_mutex);
510     ret = _push_bufr_keys_iterator(i);
511     GRIB_MUTEX_UNLOCK(&keys_iterator_mutex);
512     return ret;
513 }
514 
515 
_get_handle(int handle_id)516 static grib_handle* _get_handle(int handle_id)
517 {
518     l_grib_handle* current = handle_set;
519 
520     while (current) {
521         if (current->id == handle_id) return current->h;
522         current = current->next;
523     }
524 
525     return NULL;
526 }
527 
_get_index(int index_id)528 static grib_index* _get_index(int index_id)
529 {
530     l_grib_index* current = index_set;
531 
532     while (current) {
533         if (current->id == index_id) return current->h;
534         current = current->next;
535     }
536 
537     return NULL;
538 }
539 
_get_multi_handle(int multi_handle_id)540 static grib_multi_handle* _get_multi_handle(int multi_handle_id)
541 {
542     l_grib_multi_handle* current = multi_handle_set;
543 
544     while (current) {
545         if (current->id == multi_handle_id) return current->h;
546         current = current->next;
547     }
548 
549     return NULL;
550 }
551 
get_handle(int handle_id)552 static grib_handle* get_handle(int handle_id)
553 {
554     grib_handle* h = NULL;
555     GRIB_MUTEX_INIT_ONCE(&once, &init)
556     GRIB_MUTEX_LOCK(&handle_mutex)
557     h = _get_handle(handle_id);
558     GRIB_MUTEX_UNLOCK(&handle_mutex)
559     return h;
560 }
561 
get_index(int index_id)562 static grib_index* get_index(int index_id)
563 {
564     grib_index* h = NULL;
565     GRIB_MUTEX_INIT_ONCE(&once, &init)
566     GRIB_MUTEX_LOCK(&index_mutex)
567     h = _get_index(index_id);
568     GRIB_MUTEX_UNLOCK(&index_mutex)
569     return h;
570 }
571 
get_multi_handle(int multi_handle_id)572 static grib_multi_handle* get_multi_handle(int multi_handle_id)
573 {
574     grib_multi_handle* h = NULL;
575     GRIB_MUTEX_INIT_ONCE(&once, &init)
576     GRIB_MUTEX_LOCK(&multi_handle_mutex)
577     h = _get_multi_handle(multi_handle_id);
578     GRIB_MUTEX_UNLOCK(&multi_handle_mutex)
579     return h;
580 }
581 
get_file(int file_id)582 static FILE* get_file(int file_id)
583 {
584     l_grib_file* current = file_set;
585     while (current) {
586         if (current->id == file_id) return current->f;
587         current = current->next;
588     }
589     return NULL;
590 }
591 
_get_iterator(int iterator_id)592 static grib_iterator* _get_iterator(int iterator_id)
593 {
594     l_grib_iterator* current = iterator_set;
595 
596     while (current) {
597         if (current->id == iterator_id) return current->i;
598         current = current->next;
599     }
600     return NULL;
601 }
get_iterator(int iterator_id)602 static grib_iterator* get_iterator(int iterator_id)
603 {
604     grib_iterator* i = NULL;
605     GRIB_MUTEX_INIT_ONCE(&once, &init)
606     GRIB_MUTEX_LOCK(&iterator_mutex)
607     i = _get_iterator(iterator_id);
608     GRIB_MUTEX_UNLOCK(&iterator_mutex)
609     return i;
610 }
611 
_get_keys_iterator(int keys_iterator_id)612 static grib_keys_iterator* _get_keys_iterator(int keys_iterator_id)
613 {
614     l_grib_keys_iterator* current = keys_iterator_set;
615 
616     while (current) {
617         if (current->id == keys_iterator_id) return current->i;
618         current = current->next;
619     }
620     return NULL;
621 }
get_keys_iterator(int keys_iterator_id)622 static grib_keys_iterator* get_keys_iterator(int keys_iterator_id)
623 {
624     grib_keys_iterator* i = NULL;
625     GRIB_MUTEX_INIT_ONCE(&once, &init)
626     GRIB_MUTEX_LOCK(&keys_iterator_mutex)
627     i = _get_keys_iterator(keys_iterator_id);
628     GRIB_MUTEX_UNLOCK(&keys_iterator_mutex)
629     return i;
630 }
631 
632 //BUFR keys iterator
_get_bufr_keys_iterator(int keys_iterator_id)633 static bufr_keys_iterator* _get_bufr_keys_iterator(int keys_iterator_id)
634 {
635     l_bufr_keys_iterator* current = bufr_keys_iterator_set;
636 
637     while (current) {
638         if (current->id == keys_iterator_id) return current->i;
639         current = current->next;
640     }
641     return NULL;
642 }
get_bufr_keys_iterator(int keys_iterator_id)643 static bufr_keys_iterator* get_bufr_keys_iterator(int keys_iterator_id)
644 {
645     bufr_keys_iterator* i = NULL;
646     GRIB_MUTEX_INIT_ONCE(&once, &init)
647     GRIB_MUTEX_LOCK(&keys_iterator_mutex)
648     i = _get_bufr_keys_iterator(keys_iterator_id);
649     GRIB_MUTEX_UNLOCK(&keys_iterator_mutex)
650     return i;
651 }
652 
653 
clear_file(int file_id)654 static int clear_file(int file_id)
655 {
656     l_grib_file* current = file_set;
657     int ret              = 0;
658     while (current) {
659         if (current->id == file_id) {
660             current->id = -(current->id);
661             if (current->f) {
662                 ret = fclose(current->f);
663                 if (0 == ret) {
664                     return GRIB_SUCCESS;
665                 }
666                 else {
667                     return GRIB_IO_PROBLEM;
668                 }
669             }
670             return GRIB_SUCCESS;
671         }
672         current = current->next;
673     }
674     return GRIB_INVALID_FILE;
675 }
676 
_clear_handle(int handle_id)677 static int _clear_handle(int handle_id)
678 {
679     l_grib_handle* current = handle_set;
680 
681     /* look for the input grib id to release it */
682     while (current) {
683         if (current->id == handle_id) {
684             current->id = -(current->id);
685             if (current->h) return grib_handle_delete(current->h);
686         }
687         current = current->next;
688     }
689 
690     /* fail with invalid grib id if not found */
691     return GRIB_INVALID_GRIB;
692 }
693 
_clear_index(int index_id)694 static int _clear_index(int index_id)
695 {
696     l_grib_index* current = index_set;
697 
698     while (current) {
699         if (current->id == index_id) {
700             current->id = -(current->id);
701             if (current->h) {
702                 grib_index_delete(current->h);
703                 return GRIB_SUCCESS;
704             }
705         }
706         current = current->next;
707     }
708     return GRIB_SUCCESS;
709 }
710 
_clear_multi_handle(int multi_handle_id)711 static int _clear_multi_handle(int multi_handle_id)
712 {
713     l_grib_multi_handle* current = multi_handle_set;
714 
715     while (current) {
716         if (current->id == multi_handle_id) {
717             current->id = -(current->id);
718             if (current->h) return grib_multi_handle_delete(current->h);
719         }
720         current = current->next;
721     }
722     return GRIB_SUCCESS;
723 }
724 
clear_handle(int handle_id)725 static int clear_handle(int handle_id)
726 {
727     int ret = 0;
728     GRIB_MUTEX_INIT_ONCE(&once, &init)
729     GRIB_MUTEX_LOCK(&handle_mutex)
730     ret = _clear_handle(handle_id);
731     GRIB_MUTEX_UNLOCK(&handle_mutex)
732     return ret;
733 }
734 
clear_index(int index_id)735 static int clear_index(int index_id)
736 {
737     int ret = 0;
738     GRIB_MUTEX_INIT_ONCE(&once, &init)
739     GRIB_MUTEX_LOCK(&index_mutex)
740     ret = _clear_index(index_id);
741     GRIB_MUTEX_UNLOCK(&index_mutex)
742     return ret;
743 }
744 
clear_multi_handle(int multi_handle_id)745 static int clear_multi_handle(int multi_handle_id)
746 {
747     int ret = 0;
748     GRIB_MUTEX_INIT_ONCE(&once, &init)
749     GRIB_MUTEX_LOCK(&multi_handle_mutex)
750     ret = _clear_multi_handle(multi_handle_id);
751     GRIB_MUTEX_UNLOCK(&multi_handle_mutex)
752     return ret;
753 }
754 
_clear_iterator(int iterator_id)755 static int _clear_iterator(int iterator_id)
756 {
757     l_grib_iterator* current = iterator_set;
758 
759     while (current) {
760         if (current->id == iterator_id) {
761             current->id = -(current->id);
762             return grib_iterator_delete(current->i);
763         }
764         current = current->next;
765     }
766     return GRIB_INVALID_ITERATOR;
767 }
768 
clear_iterator(int iterator_id)769 static int clear_iterator(int iterator_id)
770 {
771     int ret = 0;
772     GRIB_MUTEX_INIT_ONCE(&once, &init)
773     GRIB_MUTEX_LOCK(&iterator_mutex)
774     ret = _clear_iterator(iterator_id);
775     GRIB_MUTEX_UNLOCK(&iterator_mutex)
776     return ret;
777 }
778 
_clear_keys_iterator(int keys_iterator_id)779 static int _clear_keys_iterator(int keys_iterator_id)
780 {
781     l_grib_keys_iterator* current = keys_iterator_set;
782 
783     while (current) {
784         if (current->id == keys_iterator_id) {
785             current->id = -(current->id);
786             return grib_keys_iterator_delete(current->i);
787         }
788         current = current->next;
789     }
790     return GRIB_INVALID_KEYS_ITERATOR;
791 }
clear_keys_iterator(int keys_iterator_id)792 static int clear_keys_iterator(int keys_iterator_id)
793 {
794     int ret = 0;
795     GRIB_MUTEX_INIT_ONCE(&once, &init)
796     GRIB_MUTEX_LOCK(&keys_iterator_mutex)
797     ret = _clear_keys_iterator(keys_iterator_id);
798     GRIB_MUTEX_UNLOCK(&keys_iterator_mutex)
799     return ret;
800 }
801 
802 //BUFR keys iterator
_clear_bufr_keys_iterator(int keys_iterator_id)803 static int _clear_bufr_keys_iterator(int keys_iterator_id)
804 {
805     l_bufr_keys_iterator* current = bufr_keys_iterator_set;
806 
807     while (current) {
808         if (current->id == keys_iterator_id) {
809             current->id = -(current->id);
810             return codes_bufr_keys_iterator_delete(current->i);
811         }
812         current = current->next;
813     }
814     return GRIB_INVALID_KEYS_ITERATOR;
815 }
clear_bufr_keys_iterator(int keys_iterator_id)816 static int clear_bufr_keys_iterator(int keys_iterator_id)
817 {
818     int ret = 0;
819     GRIB_MUTEX_INIT_ONCE(&once, &init);
820     GRIB_MUTEX_LOCK(&keys_iterator_mutex);
821     ret = _clear_bufr_keys_iterator(keys_iterator_id);
822     GRIB_MUTEX_UNLOCK(&keys_iterator_mutex);
823     return ret;
824 }
825 
grib_c_read_any_from_file(int * fid,char * buffer,int * nbytes)826 int grib_c_read_any_from_file(int* fid, char* buffer, int* nbytes)
827 {
828     grib_context* c;
829     int err     = 0;
830     size_t size = (size_t)nbytes;
831     FILE* f     = get_file(*fid);
832 
833     if (f) {
834         c       = grib_context_get_default();
835         err     = grib_read_any_from_file(c, f, buffer, &size);
836         *nbytes = size;
837         return err;
838     }
839     else {
840         return GRIB_INVALID_FILE;
841     }
842 }
843 
grib_c_write_file(int * fid,char * buffer,int * nbytes)844 int grib_c_write_file(int* fid, char* buffer, int* nbytes)
845 {
846     grib_context* c;
847     FILE* f = get_file(*fid);
848 
849     if (f) {
850         int ioerr;
851         c = grib_context_get_default();
852         if (fwrite(buffer, 1, *nbytes, f) != *nbytes) {
853             ioerr = errno;
854             grib_context_log(c, (GRIB_LOG_ERROR) | (GRIB_LOG_PERROR), "IO ERROR: %s", strerror(ioerr));
855             return GRIB_IO_PROBLEM;
856         }
857         return GRIB_SUCCESS;
858     }
859     else {
860         return GRIB_INVALID_FILE;
861     }
862 }
863 
grib_c_read_file(int * fid,char * buffer,int * nbytes)864 int grib_c_read_file(int* fid, char* buffer, int* nbytes)
865 {
866     grib_context* c;
867     FILE* f = get_file(*fid);
868 
869     if (f) {
870         int ioerr;
871         c = grib_context_get_default();
872         if (fread(buffer, 1, *nbytes, f) != *nbytes) {
873             ioerr = errno;
874             grib_context_log(c, (GRIB_LOG_ERROR) | (GRIB_LOG_PERROR), "IO ERROR: %s", strerror(ioerr));
875             return GRIB_IO_PROBLEM;
876         }
877         return GRIB_SUCCESS;
878     }
879     else {
880         return GRIB_INVALID_FILE;
881     }
882 }
883 
grib_c_open_file(int * fid,char * name,char * op)884 int grib_c_open_file(int* fid, char* name, char* op)
885 {
886     FILE* f   = NULL;
887     int ioerr = 0;
888     int ret   = GRIB_SUCCESS;
889 
890     /*TODO Proper context passed as external parameter */
891     grib_context* context = grib_context_get_default();
892 
893     f = fopen(name, op);
894 
895     if (!f) {
896         ioerr = errno;
897         grib_context_log(context, (GRIB_LOG_ERROR) | (GRIB_LOG_PERROR), "IO ERROR: %s: %s", strerror(ioerr), name);
898         *fid = -1;
899         ret  = GRIB_IO_PROBLEM;
900     }
901     else {
902         *fid = push_file(f);
903         ret  = GRIB_SUCCESS;
904     }
905     return ret;
906 }
907 
grib_c_close_file(int * fid)908 int grib_c_close_file(int* fid)
909 {
910     return clear_file(*fid);
911 }
912 
grib_c_multi_support_on(void)913 int grib_c_multi_support_on(void)
914 {
915     grib_multi_support_on(0);
916     return GRIB_SUCCESS;
917 }
918 
grib_c_multi_support_off(void)919 int grib_c_multi_support_off(void)
920 {
921     grib_multi_support_off(0);
922     return GRIB_SUCCESS;
923 }
924 
_grib_c_iterator_new_(int * gid,int * iterid,int * mode)925 static int _grib_c_iterator_new_(int* gid, int* iterid, int* mode)
926 {
927     int err = 0;
928     grib_handle* h;
929     grib_iterator* iter;
930 
931     h = get_handle(*gid);
932     if (!h) {
933         *iterid = -1;
934         return GRIB_NULL_HANDLE;
935     }
936     iter = grib_iterator_new(h, *mode, &err);
937     if (iter)
938         *iterid = push_iterator(iter);
939     else
940         *iterid = -1;
941     return err;
942 }
943 
grib_c_iterator_new(int * gid,int * iterid,int * mode)944 int grib_c_iterator_new(int* gid, int* iterid, int* mode)
945 {
946     int ret = 0;
947     GRIB_MUTEX_INIT_ONCE(&once, &init)
948     GRIB_MUTEX_LOCK(&iterator_mutex)
949     ret = _grib_c_iterator_new_(gid, iterid, mode);
950     GRIB_MUTEX_UNLOCK(&iterator_mutex)
951     return ret;
952 }
953 
grib_c_iterator_next(int * iterid,double * lat,double * lon,double * value)954 int grib_c_iterator_next(int* iterid, double* lat, double* lon, double* value)
955 {
956     grib_iterator* iter = get_iterator(*iterid);
957     if (!iter) return GRIB_INVALID_ITERATOR;
958     return grib_iterator_next(iter, lat, lon, value);
959 }
960 
grib_c_iterator_delete(int * iterid)961 int grib_c_iterator_delete(int* iterid)
962 {
963     return clear_iterator(*iterid);
964 }
965 
_grib_c_keys_iterator_new_(int * gid,int * iterid,char * name_space)966 static int _grib_c_keys_iterator_new_(int* gid, int* iterid, char* name_space)
967 {
968     int err = 0;
969     grib_handle* h;
970     grib_keys_iterator* iter;
971 
972     h = get_handle(*gid);
973     if (!h) {
974         *iterid = -1;
975         return GRIB_NULL_HANDLE;
976     }
977     iter = grib_keys_iterator_new(h, 0, name_space);
978     if (iter)
979         *iterid = push_keys_iterator(iter);
980     else
981         *iterid = -1;
982     return err;
983 }
grib_c_keys_iterator_new(int * gid,int * iterid,char * name_space)984 int grib_c_keys_iterator_new(int* gid, int* iterid, char* name_space)
985 {
986     int ret = 0;
987     GRIB_MUTEX_INIT_ONCE(&once, &init)
988     GRIB_MUTEX_LOCK(&keys_iterator_mutex)
989     ret = _grib_c_keys_iterator_new_(gid, iterid, name_space);
990     GRIB_MUTEX_UNLOCK(&keys_iterator_mutex)
991     return ret;
992 }
grib_c_keys_iterator_next(int * iterid)993 int grib_c_keys_iterator_next(int* iterid)
994 {
995     int ret = 0;
996 
997     grib_keys_iterator* iter = get_keys_iterator(*iterid);
998 
999     if (!iter) return GRIB_INVALID_KEYS_ITERATOR;
1000 
1001     ret = grib_keys_iterator_next(iter);
1002 
1003     return ret;
1004 }
grib_c_keys_iterator_delete(int * iterid)1005 int grib_c_keys_iterator_delete(int* iterid)
1006 {
1007     return clear_keys_iterator(*iterid);
1008 }
grib_c_keys_iterator_get_name(int * iterid,char * name,int len)1009 int grib_c_keys_iterator_get_name(int* iterid, char* name, int len)
1010 {
1011     size_t lsize   = len;
1012     char buf[1024] = {0,};
1013 
1014     grib_keys_iterator* kiter = get_keys_iterator(*iterid);
1015 
1016     if (!kiter) return GRIB_INVALID_KEYS_ITERATOR;
1017     if (grib_keys_iterator_get_accessor(kiter) == NULL)
1018         return GRIB_INVALID_KEYS_ITERATOR;
1019 
1020     sprintf(buf, "%s", grib_keys_iterator_get_name(kiter));
1021     lsize = strlen(buf);
1022 
1023     if (len < lsize) return GRIB_ARRAY_TOO_SMALL;
1024 
1025     memcpy(name, buf, lsize);
1026     name[lsize] = '\0';
1027 
1028     return 0;
1029 }
grib_c_keys_iterator_rewind(int * kiter)1030 int grib_c_keys_iterator_rewind(int* kiter)
1031 {
1032     grib_keys_iterator* i = get_keys_iterator(*kiter);
1033 
1034     if (!i) return GRIB_INVALID_KEYS_ITERATOR;
1035     return grib_keys_iterator_rewind(i);
1036 }
1037 
1038 /*BUFR keys iterator*/
_codes_c_bufr_keys_iterator_new_(int * gid,int * iterid)1039 static int _codes_c_bufr_keys_iterator_new_(int* gid, int* iterid)
1040 {
1041     int err = 0;
1042     grib_handle* h;
1043     bufr_keys_iterator* iter;
1044 
1045     h = get_handle(*gid);
1046     if (!h) {
1047         *iterid = -1;
1048         return GRIB_NULL_HANDLE;
1049     }
1050     iter = codes_bufr_keys_iterator_new(h, 0);
1051     if (iter)
1052         *iterid = push_bufr_keys_iterator(iter);
1053     else
1054         *iterid = -1;
1055     return err;
1056 }
codes_c_bufr_keys_iterator_new(int * gid,int * iterid)1057 int codes_c_bufr_keys_iterator_new(int* gid, int* iterid)
1058 {
1059     int ret = 0;
1060     GRIB_MUTEX_INIT_ONCE(&once, &init)
1061     GRIB_MUTEX_LOCK(&keys_iterator_mutex)
1062     ret = _codes_c_bufr_keys_iterator_new_(gid, iterid);
1063     GRIB_MUTEX_UNLOCK(&keys_iterator_mutex)
1064     return ret;
1065 }
1066 
codes_c_bufr_keys_iterator_next(int * iterid)1067 int codes_c_bufr_keys_iterator_next(int* iterid)
1068 {
1069     int ret                  = 0;
1070     bufr_keys_iterator* iter = get_bufr_keys_iterator(*iterid);
1071 
1072     if (!iter) return GRIB_INVALID_KEYS_ITERATOR;
1073 
1074     ret = codes_bufr_keys_iterator_next(iter);
1075     return ret;
1076 }
1077 
codes_c_bufr_keys_iterator_get_name(int * iterid,char * name,int len)1078 int codes_c_bufr_keys_iterator_get_name(int* iterid, char* name, int len)
1079 {
1080     size_t lsize   = len;
1081     char buf[1024] = {0,};
1082 
1083     bufr_keys_iterator* kiter = get_bufr_keys_iterator(*iterid);
1084 
1085     if (!kiter) return GRIB_INVALID_KEYS_ITERATOR;
1086     if (codes_bufr_keys_iterator_get_accessor(kiter) == NULL)
1087         return GRIB_INVALID_KEYS_ITERATOR;
1088 
1089     sprintf(buf, "%s", codes_bufr_keys_iterator_get_name(kiter));
1090     lsize = strlen(buf);
1091 
1092     if (len < lsize) return GRIB_ARRAY_TOO_SMALL;
1093 
1094     memcpy(name, buf, lsize);
1095     name[lsize] = '\0';
1096 
1097     return 0;
1098 }
1099 
codes_c_bufr_keys_iterator_rewind(int * kiter)1100 int codes_c_bufr_keys_iterator_rewind(int* kiter)
1101 {
1102     bufr_keys_iterator* i = get_bufr_keys_iterator(*kiter);
1103 
1104     if (!i) return GRIB_INVALID_KEYS_ITERATOR;
1105     return codes_bufr_keys_iterator_rewind(i);
1106 }
1107 
codes_c_bufr_keys_iterator_delete(int * iterid)1108 int codes_c_bufr_keys_iterator_delete(int* iterid)
1109 {
1110     return clear_bufr_keys_iterator(*iterid);
1111 }
1112 
1113 
grib_c_gribex_mode_on(void)1114 int grib_c_gribex_mode_on(void)
1115 {
1116     grib_gribex_mode_on(0);
1117     return GRIB_SUCCESS;
1118 }
1119 
grib_c_gribex_mode_off(void)1120 int grib_c_gribex_mode_off(void)
1121 {
1122     grib_gribex_mode_off(0);
1123     return GRIB_SUCCESS;
1124 }
1125 
grib_c_skip_computed(int * iterid)1126 int grib_c_skip_computed(int* iterid)
1127 {
1128     grib_keys_iterator* iter = get_keys_iterator(*iterid);
1129     if (!iter) return GRIB_INVALID_KEYS_ITERATOR;
1130     return grib_keys_iterator_set_flags(iter, GRIB_KEYS_ITERATOR_SKIP_COMPUTED);
1131 }
1132 
grib_c_skip_coded(int * iterid)1133 int grib_c_skip_coded(int* iterid)
1134 {
1135     grib_keys_iterator* iter = get_keys_iterator(*iterid);
1136     if (!iter) return GRIB_INVALID_KEYS_ITERATOR;
1137     return grib_keys_iterator_set_flags(iter, GRIB_KEYS_ITERATOR_SKIP_CODED);
1138 }
1139 
grib_c_skip_edition_specific(int * iterid)1140 int grib_c_skip_edition_specific(int* iterid)
1141 {
1142     grib_keys_iterator* iter = get_keys_iterator(*iterid);
1143     if (!iter) return GRIB_INVALID_KEYS_ITERATOR;
1144     return grib_keys_iterator_set_flags(iter, GRIB_KEYS_ITERATOR_SKIP_EDITION_SPECIFIC);
1145 }
1146 
grib_c_skip_duplicates(int * iterid)1147 int grib_c_skip_duplicates(int* iterid)
1148 {
1149     grib_keys_iterator* iter = get_keys_iterator(*iterid);
1150     if (!iter) return GRIB_INVALID_KEYS_ITERATOR;
1151     return grib_keys_iterator_set_flags(iter, GRIB_KEYS_ITERATOR_SKIP_DUPLICATES);
1152 }
1153 
grib_c_skip_read_only(int * iterid)1154 int grib_c_skip_read_only(int* iterid)
1155 {
1156     grib_keys_iterator* iter = get_keys_iterator(*iterid);
1157     if (!iter) return GRIB_INVALID_KEYS_ITERATOR;
1158     return grib_keys_iterator_set_flags(iter, GRIB_KEYS_ITERATOR_SKIP_READ_ONLY);
1159 }
1160 
grib_c_skip_function(int * iterid)1161 int grib_c_skip_function(int* iterid)
1162 {
1163     grib_keys_iterator* iter = get_keys_iterator(*iterid);
1164     if (!iter) return GRIB_INVALID_KEYS_ITERATOR;
1165     return grib_keys_iterator_set_flags(iter, GRIB_KEYS_ITERATOR_SKIP_FUNCTION);
1166 }
1167 
grib_c_new_from_message(int * gid,void * buffer,size_t * bufsize)1168 int grib_c_new_from_message(int* gid, void* buffer, size_t* bufsize)
1169 {
1170     grib_handle* h = NULL;
1171     h              = grib_handle_new_from_message_copy(0, buffer, *bufsize);
1172     if (h) {
1173         push_handle(h, gid);
1174         return GRIB_SUCCESS;
1175     }
1176 
1177     *gid = -1;
1178     return GRIB_INTERNAL_ERROR;
1179 }
1180 
grib_c_new_from_message_copy(int * gid,void * buffer,size_t * bufsize)1181 int grib_c_new_from_message_copy(int* gid, void* buffer, size_t* bufsize)
1182 {
1183     grib_handle* h = NULL;
1184     h              = grib_handle_new_from_message_copy(0, buffer, *bufsize);
1185     if (h) {
1186         push_handle(h, gid);
1187         return GRIB_SUCCESS;
1188     }
1189 
1190     *gid = -1;
1191     return GRIB_INTERNAL_ERROR;
1192 }
1193 
grib_c_grib_new_from_samples(int * gid,char * name)1194 int grib_c_grib_new_from_samples(int* gid, char* name)
1195 {
1196     grib_handle* h = NULL;
1197 
1198     h = grib_handle_new_from_samples(NULL, name);
1199     /*   grib_context_set_debug(h->context,1);*/
1200 
1201     if (h) {
1202         push_handle(h, gid);
1203         return GRIB_SUCCESS;
1204     }
1205 
1206     *gid = -1;
1207     return GRIB_FILE_NOT_FOUND;
1208 }
1209 
grib_c_bufr_new_from_samples(int * gid,char * name)1210 int grib_c_bufr_new_from_samples(int* gid, char* name)
1211 {
1212     grib_handle* h = NULL;
1213 
1214     h = codes_bufr_handle_new_from_samples(NULL, name);
1215     /*   grib_context_set_debug(h->context,1);*/
1216 
1217     if (h) {
1218         push_handle(h, gid);
1219         return GRIB_SUCCESS;
1220     }
1221 
1222     *gid = -1;
1223     return GRIB_FILE_NOT_FOUND;
1224 }
1225 
grib_c_clone(int * gidsrc,int * giddest)1226 int grib_c_clone(int* gidsrc, int* giddest)
1227 {
1228     grib_handle* src  = get_handle(*gidsrc);
1229     grib_handle* dest = NULL;
1230 
1231     if (src) {
1232         dest = grib_handle_clone(src);
1233         if (dest) {
1234             push_handle(dest, giddest);
1235             return GRIB_SUCCESS;
1236         }
1237     }
1238 
1239     *giddest = -1;
1240     return GRIB_INVALID_GRIB;
1241 }
1242 
grib_c_copy_namespace(int * gidsrc,char * name,int * giddest)1243 int grib_c_copy_namespace(int* gidsrc, char* name, int* giddest)
1244 {
1245     grib_handle* src  = get_handle(*gidsrc);
1246     grib_handle* dest = get_handle(*giddest);
1247 
1248     if (src && dest)
1249         return grib_copy_namespace(dest, name, src);
1250 
1251     return GRIB_INVALID_GRIB;
1252 }
1253 
grib_c_count_in_file(FILE * f,int * n)1254 int grib_c_count_in_file(FILE* f, int* n)
1255 {
1256     int err = 0;
1257     if (f) err = grib_count_in_file(0, f, n);
1258     return err;
1259 }
1260 
grib_c_new_gts_from_file(FILE * f,int headers_only,int * gid)1261 int grib_c_new_gts_from_file(FILE* f, int headers_only, int* gid)
1262 {
1263     grib_handle* h = NULL;
1264     int err        = 0;
1265 
1266     if (f) {
1267         h = gts_new_from_file(0, f, &err);
1268 
1269         if (h) {
1270             push_handle(h, gid);
1271             return GRIB_SUCCESS;
1272         }
1273         else {
1274             *gid = -1;
1275             return GRIB_END_OF_FILE;
1276         }
1277     }
1278 
1279     *gid = -1;
1280     return GRIB_INVALID_FILE;
1281 }
1282 
grib_c_new_metar_from_file(FILE * f,int headers_only,int * gid)1283 int grib_c_new_metar_from_file(FILE* f, int headers_only, int* gid)
1284 {
1285     grib_handle* h = NULL;
1286     int err        = 0;
1287 
1288     if (f) {
1289         h = metar_new_from_file(0, f, &err);
1290 
1291         if (h) {
1292             push_handle(h, gid);
1293             return GRIB_SUCCESS;
1294         }
1295         else {
1296             *gid = -1;
1297             return GRIB_END_OF_FILE;
1298         }
1299     }
1300 
1301     *gid = -1;
1302     return GRIB_INVALID_FILE;
1303 }
1304 
grib_c_new_any_from_file(FILE * f,int headers_only,int * gid)1305 int grib_c_new_any_from_file(FILE* f, int headers_only, int* gid)
1306 {
1307     grib_handle* h = NULL;
1308     int err        = 0;
1309     if (f) {
1310         h = codes_handle_new_from_file(0, f, PRODUCT_ANY, &err);
1311         if (h) {
1312             push_handle(h, gid);
1313             return GRIB_SUCCESS;
1314         }
1315         else {
1316             *gid = -1;
1317             return GRIB_END_OF_FILE;
1318         }
1319     }
1320 
1321     *gid = -1;
1322     return GRIB_INVALID_FILE;
1323 }
1324 
grib_c_new_bufr_from_file(FILE * f,int headers_only,int * gid)1325 int grib_c_new_bufr_from_file(FILE* f, int headers_only, int* gid)
1326 {
1327     grib_handle* h = NULL;
1328     int err        = 0;
1329 
1330     if (f) {
1331         /* h = bufr_new_from_file(0,f,headers_only,&err); */
1332         h = codes_handle_new_from_file(0, f, PRODUCT_BUFR, &err);
1333 
1334         if (h) {
1335             push_handle(h, gid);
1336             return GRIB_SUCCESS;
1337         }
1338         else {
1339             *gid = -1;
1340             return GRIB_END_OF_FILE;
1341         }
1342     }
1343 
1344     *gid = -1;
1345     return GRIB_INVALID_FILE;
1346 }
1347 
grib_c_new_from_file(FILE * f,int * gid,int headers_only)1348 int grib_c_new_from_file(FILE* f, int* gid, int headers_only)
1349 {
1350     grib_handle* h = NULL;
1351     int err        = 0;
1352 
1353     if (f) {
1354         h = grib_new_from_file(0, f, headers_only, &err);
1355 
1356         if (h) {
1357             push_handle(h, gid);
1358             return GRIB_SUCCESS;
1359         }
1360         else {
1361             *gid = -1;
1362             if (err == GRIB_SUCCESS) {
1363                 return GRIB_END_OF_FILE;
1364             }
1365             else {
1366                 /* A real error occurred */
1367                 return err;
1368             }
1369         }
1370     }
1371 
1372     *gid = -1;
1373     return GRIB_INVALID_FILE;
1374 }
1375 
grib_c_new_from_index(int * iid,int * gid)1376 int grib_c_new_from_index(int* iid, int* gid)
1377 {
1378     int err       = 0;
1379     grib_index* i = get_index(*iid);
1380 
1381     grib_handle* h = NULL;
1382 
1383     if (i) {
1384         h = grib_handle_new_from_index(i, &err);
1385         if (h) {
1386             push_handle(h, gid);
1387             return GRIB_SUCCESS;
1388         }
1389         else {
1390             *gid = -1;
1391             return GRIB_END_OF_INDEX;
1392         }
1393     }
1394 
1395     *gid = -1;
1396     return GRIB_INVALID_INDEX;
1397 }
1398 
grib_c_index_new_from_file(char * file,char * keys,int * gid)1399 int grib_c_index_new_from_file(char* file, char* keys, int* gid)
1400 {
1401     int err       = 0;
1402     grib_index* i = NULL;
1403 
1404     if (*file) {
1405         i = grib_index_new_from_file(0, file, keys, &err);
1406         if (i) {
1407             push_index(i, gid);
1408             return GRIB_SUCCESS;
1409         }
1410         else {
1411             *gid = -1;
1412             return GRIB_END_OF_FILE;
1413         }
1414     }
1415 
1416     *gid = -1;
1417     return GRIB_INVALID_FILE;
1418 }
1419 
grib_c_index_add_file(int * iid,char * file)1420 int grib_c_index_add_file(int* iid, char* file)
1421 {
1422     grib_index* i = get_index(*iid);
1423     int err       = GRIB_SUCCESS;
1424 
1425     if (!i) {
1426         return GRIB_INVALID_INDEX;
1427     }
1428     else {
1429         err = grib_index_add_file(i, file);
1430         return err;
1431     }
1432 }
1433 
grib_c_index_release(int * hid)1434 int grib_c_index_release(int* hid)
1435 {
1436     return clear_index(*hid);
1437 }
1438 
grib_c_multi_release(int * hid)1439 int grib_c_multi_release(int* hid)
1440 {
1441     return clear_multi_handle(*hid);
1442 }
1443 
grib_c_release(int * hid)1444 int grib_c_release(int* hid)
1445 {
1446     return clear_handle(*hid);
1447 }
1448 
grib_c_dump(int * gid)1449 int grib_c_dump(int* gid)
1450 {
1451     grib_handle* h = get_handle(*gid);
1452 
1453     if (!h)
1454         return GRIB_INVALID_GRIB;
1455     else
1456         grib_dump_content(h, stdout, "wmo", 0, NULL);
1457 
1458     return GRIB_SUCCESS;
1459 }
1460 
grib_c_print(int * gid,char * key)1461 int grib_c_print(int* gid, char* key)
1462 {
1463     grib_handle* h = get_handle(*gid);
1464     int err        = GRIB_SUCCESS;
1465     grib_dumper* d = NULL;
1466 
1467     if (!h) {
1468         return GRIB_INVALID_GRIB;
1469     }
1470     else {
1471         d   = grib_dumper_factory("serialize", h, stdout, 0, 0);
1472         err = grib_print(h, key, d);
1473         grib_dumper_delete(d);
1474         return err;
1475     }
1476 }
1477 
grib_c_get_error_string(int * err,char * buf,int len)1478 int grib_c_get_error_string(int* err, char* buf, int len)
1479 {
1480     const char* err_msg = grib_get_error_message(*err);
1481     size_t erlen        = strlen(err_msg);
1482     if (len <= erlen) return GRIB_ARRAY_TOO_SMALL;
1483 
1484     strncpy(buf, err_msg, (size_t)erlen);
1485     buf[erlen] = '\0';
1486 
1487     return GRIB_SUCCESS;
1488 }
1489 
grib_c_get_size_int(int * gid,char * key,int * val)1490 int grib_c_get_size_int(int* gid, char* key, int* val)
1491 {
1492     grib_handle* h = get_handle(*gid);
1493     int err        = GRIB_SUCCESS;
1494     size_t tsize   = 0;
1495 
1496     if (!h) {
1497         return GRIB_INVALID_GRIB;
1498     }
1499     else {
1500         err  = grib_get_size(h, key, &tsize);
1501         *val = tsize;
1502         return err;
1503     }
1504 }
1505 
grib_c_get_message_offset(int * gid,size_t * offset)1506 int grib_c_get_message_offset(int* gid, size_t* offset)
1507 {
1508     int err = GRIB_SUCCESS;
1509     off_t myoffset;
1510     grib_handle* h = get_handle(*gid);
1511 
1512     if (!h)
1513         return GRIB_INVALID_GRIB;
1514     else {
1515         err     = grib_get_message_offset(h, &myoffset);
1516         *offset = myoffset;
1517         return err;
1518     }
1519 }
1520 
grib_c_get_message_size(int * gid,size_t * size)1521 int grib_c_get_message_size(int* gid, size_t* size)
1522 {
1523     grib_handle* h = get_handle(*gid);
1524 
1525     if (!h)
1526         return GRIB_INVALID_GRIB;
1527     else
1528         return grib_get_message_size(h, size);
1529 }
1530 
grib_c_get_string_length(int * gid,char * key,size_t * val)1531 int grib_c_get_string_length(int* gid, char* key, size_t* val)
1532 {
1533     grib_handle* h = get_handle(*gid);
1534 
1535     if (!h)
1536         return GRIB_INVALID_GRIB;
1537     else
1538         return grib_get_string_length(h, key, val);
1539 }
1540 
grib_c_get_size_long(int * gid,char * key,long * val)1541 int grib_c_get_size_long(int* gid, char* key, long* val)
1542 {
1543     grib_handle* h = get_handle(*gid);
1544     int err        = GRIB_SUCCESS;
1545     size_t tsize   = 0;
1546 
1547     if (!h) {
1548         return GRIB_INVALID_GRIB;
1549     }
1550     else {
1551         err  = grib_get_size(h, key, &tsize);
1552         *val = tsize;
1553         return err;
1554     }
1555 }
1556 
grib_c_index_get_size_int(int * gid,char * key,int * val)1557 int grib_c_index_get_size_int(int* gid, char* key, int* val)
1558 {
1559     grib_index* h = get_index(*gid);
1560     int err       = GRIB_SUCCESS;
1561     size_t tsize  = 0;
1562 
1563     if (!h) {
1564         return GRIB_INVALID_GRIB;
1565     }
1566     else {
1567         err  = grib_index_get_size(h, key, &tsize);
1568         *val = tsize;
1569         return err;
1570     }
1571 }
1572 
grib_c_index_get_size_long(int * gid,char * key,long * val)1573 int grib_c_index_get_size_long(int* gid, char* key, long* val)
1574 {
1575     grib_index* h = get_index(*gid);
1576     int err       = GRIB_SUCCESS;
1577     size_t tsize  = 0;
1578 
1579     if (!h) {
1580         return GRIB_INVALID_GRIB;
1581     }
1582     else {
1583         err  = grib_index_get_size(h, key, &tsize);
1584         *val = tsize;
1585         return err;
1586     }
1587 }
1588 
grib_c_get_int(int * gid,char * key,int * val)1589 int grib_c_get_int(int* gid, char* key, int* val)
1590 {
1591     grib_handle* h = get_handle(*gid);
1592     long long_val;
1593     int err = GRIB_SUCCESS;
1594 
1595     if (!h) return GRIB_INVALID_GRIB;
1596     err  = grib_get_long(h, key, &long_val);
1597     *val = long_val;
1598     return err;
1599 }
1600 
grib_c_get_long(int * gid,char * key,long * val)1601 int grib_c_get_long(int* gid, char* key, long* val)
1602 {
1603     grib_handle* h = get_handle(*gid);
1604     int err        = GRIB_SUCCESS;
1605 
1606     if (!h) return GRIB_INVALID_GRIB;
1607     err = grib_get_long(h, key, val);
1608     return err;
1609 }
1610 
grib_c_get_double(int * gid,char * key,double * val)1611 int grib_c_get_double(int* gid, char* key, double* val)
1612 {
1613     grib_handle* h = get_handle(*gid);
1614     int err        = GRIB_SUCCESS;
1615 
1616     if (!h) return GRIB_INVALID_GRIB;
1617     err = grib_get_double(h, key, val);
1618     return err;
1619 }
1620 
grib_c_get_int_array(int * gid,char * key,int * val,int * size)1621 int grib_c_get_int_array(int* gid, char* key, int* val, int* size)
1622 {
1623     grib_handle* h = get_handle(*gid);
1624     long* long_val = NULL;
1625     int err        = GRIB_SUCCESS;
1626     size_t lsize   = *size;
1627 
1628     if (!h) return GRIB_INVALID_GRIB;
1629 
1630     if (sizeof(long) == sizeof(int)) {
1631         long_val = (long*)val;
1632         err      = grib_get_long_array(h, key, long_val, &lsize);
1633         *size    = lsize;
1634         return err;
1635     }
1636     if (*size)
1637         long_val = grib_context_malloc(h->context, (*size) * (sizeof(long)));
1638     else
1639         long_val = grib_context_malloc(h->context, (sizeof(long)));
1640 
1641     if (!long_val) return GRIB_OUT_OF_MEMORY;
1642     err = grib_get_long_array(h, key, long_val, &lsize);
1643 
1644     for (*size = 0; *size < lsize; (*size)++)
1645         val[*size] = long_val[*size];
1646 
1647     grib_context_free(h->context, long_val);
1648     return err;
1649 }
1650 
grib_c_get_long_array(int * gid,char * key,long * val,int * size)1651 int grib_c_get_long_array(int* gid, char* key, long* val, int* size)
1652 {
1653     grib_handle* h = get_handle(*gid);
1654     int err        = GRIB_SUCCESS;
1655     size_t lsize   = *size;
1656 
1657     if (!h) return GRIB_INVALID_GRIB;
1658 
1659     err   = grib_get_long_array(h, key, val, &lsize);
1660     *size = lsize;
1661 
1662     return err;
1663 }
1664 
grib_c_index_get_string(int * gid,char * key,char * val,int * eachsize,int * size)1665 int grib_c_index_get_string(int* gid, char* key, char* val, int* eachsize, int* size)
1666 {
1667     grib_index* h = get_index(*gid);
1668     int err       = GRIB_SUCCESS;
1669     int i;
1670     size_t lsize = *size;
1671     char** bufval;
1672     char* p = val;
1673 
1674     if (!h) return GRIB_INVALID_GRIB;
1675 
1676     bufval = (char**)grib_context_malloc_clear(h->context, sizeof(char*) * *size);
1677 
1678     err   = grib_index_get_string(h, key, bufval, &lsize);
1679     *size = lsize;
1680 
1681     if (err) return err;
1682 
1683     for (i = 0; i < lsize; i++) {
1684         int l = strlen(bufval[i]);
1685         int j;
1686         if (*eachsize < l) {
1687             grib_context_free(h->context, bufval);
1688             printf("eachsize=%d strlen(bufval[i])=%d\n", *eachsize, (unsigned int)strlen(bufval[i]));
1689             return GRIB_ARRAY_TOO_SMALL;
1690         }
1691         memcpy(p, bufval[i], l);
1692         p += l;
1693         for (j = 0; j < *eachsize - l; j++)
1694             *(p++) = ' ';
1695     }
1696     grib_context_free(h->context, bufval);
1697 
1698     return err;
1699 }
1700 
grib_c_index_get_long(int * gid,char * key,long * val,int * size)1701 int grib_c_index_get_long(int* gid, char* key, long* val, int* size)
1702 {
1703     grib_index* h = get_index(*gid);
1704     int err       = GRIB_SUCCESS;
1705     size_t lsize  = *size;
1706 
1707     if (!h) return GRIB_INVALID_GRIB;
1708     err   = grib_index_get_long(h, key, val, &lsize);
1709     *size = lsize;
1710     return err;
1711 }
1712 
grib_c_index_get_int(int * gid,char * key,int * val,int * size)1713 int grib_c_index_get_int(int* gid, char* key, int* val, int* size)
1714 {
1715     grib_index* h = get_index(*gid);
1716     int err       = GRIB_SUCCESS;
1717     size_t lsize  = *size;
1718     long* lval    = 0;
1719     int i;
1720 
1721     if (!h) return GRIB_INVALID_GRIB;
1722 
1723     lval = grib_context_malloc(h->context, sizeof(long) * *size);
1724     if (!lval) return GRIB_OUT_OF_MEMORY;
1725 
1726     err = grib_index_get_long(h, key, lval, &lsize);
1727     for (i = 0; i < lsize; i++)
1728         val[i] = lval[i];
1729 
1730     *size = lsize;
1731     return err;
1732 }
1733 
grib_c_index_get_real8(int * gid,char * key,double * val,int * size)1734 int grib_c_index_get_real8(int* gid, char* key, double* val, int* size)
1735 {
1736     grib_index* h = get_index(*gid);
1737     int err       = GRIB_SUCCESS;
1738     size_t lsize  = *size;
1739 
1740     if (!h) return GRIB_INVALID_GRIB;
1741     err   = grib_index_get_double(h, key, val, &lsize);
1742     *size = lsize;
1743     return err;
1744 }
1745 
grib_c_set_int_array(int * gid,char * key,int * val,int * size)1746 int grib_c_set_int_array(int* gid, char* key, int* val, int* size)
1747 {
1748     grib_handle* h = get_handle(*gid);
1749     int err        = GRIB_SUCCESS;
1750     long* long_val = NULL;
1751     size_t lsize   = *size;
1752 
1753     if (!h) return GRIB_INVALID_GRIB;
1754 
1755     if (sizeof(long) == sizeof(int)) {
1756         long_val = (long*)val;
1757         return grib_set_long_array(h, key, long_val, lsize);
1758     }
1759 
1760     if (lsize)
1761         long_val = grib_context_malloc(h->context, (lsize) * (sizeof(long)));
1762     else
1763         long_val = grib_context_malloc(h->context, (sizeof(long)));
1764 
1765     if (!long_val) return GRIB_OUT_OF_MEMORY;
1766 
1767     for (lsize = 0; lsize < (*size); lsize++)
1768         long_val[lsize] = val[lsize];
1769 
1770     err = grib_set_long_array(h, key, long_val, lsize);
1771 
1772     grib_context_free(h->context, long_val);
1773     return err;
1774 }
1775 
grib_c_set_long_array(int * gid,char * key,long * val,int * size)1776 int grib_c_set_long_array(int* gid, char* key, long* val, int* size)
1777 {
1778     grib_handle* h = get_handle(*gid);
1779     int err        = GRIB_SUCCESS;
1780     size_t lsize   = *size;
1781 
1782     if (!h) return GRIB_INVALID_GRIB;
1783 
1784     return grib_set_long_array(h, key, val, lsize);
1785 
1786     return err;
1787 }
1788 
grib_c_set_int(int * gid,char * key,int * val)1789 int grib_c_set_int(int* gid, char* key, int* val)
1790 {
1791     grib_handle* h = get_handle(*gid);
1792     long long_val  = *val;
1793     if (!h) return GRIB_INVALID_GRIB;
1794     return grib_set_long(h, key, long_val);
1795 }
1796 
grib_c_set_long(int * gid,char * key,long * val)1797 int grib_c_set_long(int* gid, char* key, long* val)
1798 {
1799     grib_handle* h = get_handle(*gid);
1800     if (!h) return GRIB_INVALID_GRIB;
1801     return grib_set_long(h, key, *val);
1802 }
1803 
grib_c_set_missing(int * gid,char * key)1804 int grib_c_set_missing(int* gid, char* key)
1805 {
1806     grib_handle* h = get_handle(*gid);
1807     if (!h) return GRIB_INVALID_GRIB;
1808 
1809     return grib_set_missing(h, key);
1810 }
1811 
1812 /*
1813  * Submits all keys with the given values in one go.
1814  * 'keyvals' is a string of the form:
1815  *    key1=val1,key2=val2,key3=val3
1816  */
grib_c_set_key_vals(int * gid,char * keyvals)1817 int grib_c_set_key_vals(int* gid, char* keyvals)
1818 {
1819     grib_handle* h = get_handle(*gid);
1820     if (!h) return GRIB_INVALID_GRIB;
1821     {
1822         int err                  = GRIB_SUCCESS;
1823         grib_values values[1024] = {{0,},};
1824         int count = 1000; /* max. num key/val pairs */
1825         if ((err = parse_keyval_string(NULL, keyvals, 1, GRIB_TYPE_UNDEFINED, values, &count)) != GRIB_SUCCESS) {
1826             return err;
1827         }
1828         if ((err = grib_set_values(h, values, count)) != GRIB_SUCCESS) {
1829             return err;
1830         }
1831     }
1832     return GRIB_SUCCESS;
1833 }
1834 
grib_c_is_missing(int * gid,char * key,int * isMissing)1835 int grib_c_is_missing(int* gid, char* key, int* isMissing)
1836 {
1837     int err        = 0;
1838     grib_handle* h = get_handle(*gid);
1839     if (!h) return GRIB_INVALID_GRIB;
1840 
1841     *isMissing = grib_is_missing(h, key, &err);
1842     return err;
1843 }
1844 
grib_c_is_defined(int * gid,char * key,int * isDefined)1845 int grib_c_is_defined(int* gid, char* key, int* isDefined)
1846 {
1847     grib_handle* h = get_handle(*gid);
1848     if (!h) return GRIB_INVALID_GRIB;
1849 
1850     *isDefined = grib_is_defined(h, key);
1851     return GRIB_SUCCESS;
1852 }
1853 
grib_c_set_real4(int * gid,char * key,float * val)1854 int grib_c_set_real4(int* gid, char* key, float* val)
1855 {
1856     grib_handle* h = get_handle(*gid);
1857     double val8    = *val;
1858     if (!h) return GRIB_INVALID_GRIB;
1859 
1860     return grib_set_double(h, key, val8);
1861 }
1862 
grib_c_get_real4_element(int * gid,char * key,int * index,float * val)1863 int grib_c_get_real4_element(int* gid, char* key, int* index, float* val)
1864 {
1865     grib_handle* h = get_handle(*gid);
1866     int err        = GRIB_SUCCESS;
1867     double val8    = 0;
1868 
1869     if (!h) return GRIB_INVALID_GRIB;
1870 
1871     err  = grib_get_double_element(h, key, *index, &val8);
1872     *val = val8;
1873     return err;
1874 }
1875 
grib_c_get_real4_elements(int * gid,char * key,int * index,float * val,int * size)1876 int grib_c_get_real4_elements(int* gid, char* key, int* index, float* val, int* size)
1877 {
1878     grib_handle* h = get_handle(*gid);
1879     int err        = GRIB_SUCCESS;
1880     size_t lsize   = *size;
1881     long i         = 0;
1882     double* val8   = NULL;
1883 
1884     if (!h) return GRIB_INVALID_GRIB;
1885 
1886     if (*size)
1887         val8 = grib_context_malloc(h->context, (*size) * (sizeof(double)));
1888     else
1889         val8 = grib_context_malloc(h->context, sizeof(double));
1890 
1891     if (!val8) return GRIB_OUT_OF_MEMORY;
1892 
1893 
1894     err = grib_get_double_elements(h, key, index, (long)lsize, val8);
1895 
1896     for (i = 0; i < lsize; (i)++)
1897         val[i] = val8[i];
1898 
1899     grib_context_free(h->context, val8);
1900 
1901     return err;
1902 }
1903 
grib_c_get_real4(int * gid,char * key,float * val)1904 int grib_c_get_real4(int* gid, char* key, float* val)
1905 {
1906     grib_handle* h = get_handle(*gid);
1907     int err        = GRIB_SUCCESS;
1908     double val8    = 0;
1909 
1910     if (!h) return GRIB_INVALID_GRIB;
1911 
1912     err  = grib_get_double(h, key, &val8);
1913     *val = val8;
1914     return err;
1915 }
1916 
grib_c_get_real4_array(int * gid,char * key,float * val,int * size)1917 int grib_c_get_real4_array(int* gid, char* key, float* val, int* size)
1918 {
1919     grib_handle* h = get_handle(*gid);
1920     int err        = GRIB_SUCCESS;
1921     size_t lsize   = *size;
1922     double* val8   = NULL;
1923 
1924     if (!h) return GRIB_INVALID_GRIB;
1925 
1926     if (*size)
1927         val8 = grib_context_malloc(h->context, (*size) * (sizeof(double)));
1928     else
1929         val8 = grib_context_malloc(h->context, sizeof(double));
1930 
1931     if (!val8) return GRIB_OUT_OF_MEMORY;
1932 
1933     err = grib_get_double_array(h, key, val8, &lsize);
1934 
1935     for (*size = 0; *size < lsize; (*size)++)
1936         val[*size] = val8[*size];
1937 
1938     grib_context_free(h->context, val8);
1939 
1940     return err;
1941 }
1942 
grib_c_set_real4_array(int * gid,char * key,float * val,int * size)1943 int grib_c_set_real4_array(int* gid, char* key, float* val, int* size)
1944 {
1945     grib_handle* h = get_handle(*gid);
1946     int err        = GRIB_SUCCESS;
1947     size_t lsize   = *size;
1948     double* val8   = NULL;
1949 
1950     if (!h) return GRIB_INVALID_GRIB;
1951 
1952     if (*size)
1953         val8 = grib_context_malloc(h->context, lsize * (sizeof(double)));
1954     else
1955         val8 = grib_context_malloc(h->context, sizeof(double));
1956 
1957     if (!val8) return GRIB_OUT_OF_MEMORY;
1958 
1959     for (lsize = 0; lsize < *size; lsize++)
1960         val8[lsize] = val[lsize];
1961 
1962     err = grib_set_double_array(h, key, val8, lsize);
1963     grib_context_free(h->context, val8);
1964     return err;
1965 }
1966 
grib_c_index_select_real8(int * gid,char * key,double * val)1967 int grib_c_index_select_real8(int* gid, char* key, double* val)
1968 {
1969     grib_index* h = get_index(*gid);
1970 
1971     if (!h) return GRIB_INVALID_GRIB;
1972     return grib_index_select_double(h, key, *val);
1973 }
1974 
grib_c_index_select_string(int * gid,char * key,char * val)1975 int grib_c_index_select_string(int* gid, char* key, char* val)
1976 {
1977     grib_index* h = get_index(*gid);
1978 
1979     if (!h) return GRIB_INVALID_GRIB;
1980     return grib_index_select_string(h, key, val);
1981 }
1982 
grib_c_index_select_int(int * gid,char * key,int * val)1983 int grib_c_index_select_int(int* gid, char* key, int* val)
1984 {
1985     grib_index* h = get_index(*gid);
1986     long lval     = *val;
1987 
1988     if (!h) return GRIB_INVALID_GRIB;
1989     return grib_index_select_long(h, key, lval);
1990 }
1991 
grib_c_index_select_long(int * gid,char * key,long * val)1992 int grib_c_index_select_long(int* gid, char* key, long* val)
1993 {
1994     grib_index* h = get_index(*gid);
1995 
1996     if (!h) return GRIB_INVALID_GRIB;
1997     return grib_index_select_long(h, key, *val);
1998 }
1999 
grib_c_set_real8(int * gid,char * key,double * val)2000 int grib_c_set_real8(int* gid, char* key, double* val)
2001 {
2002     grib_handle* h = get_handle(*gid);
2003 
2004     if (!h) return GRIB_INVALID_GRIB;
2005     return grib_set_double(h, key, *val);
2006 }
2007 
grib_c_get_real8(int * gid,char * key,double * val)2008 int grib_c_get_real8(int* gid, char* key, double* val)
2009 {
2010     grib_handle* h = get_handle(*gid);
2011 
2012     if (!h) return GRIB_INVALID_GRIB;
2013 
2014     return grib_get_double(h, key, val);
2015 }
2016 
grib_c_set_double(int * gid,char * key,double * val)2017 int grib_c_set_double(int* gid, char* key, double* val)
2018 {
2019     grib_handle* h = get_handle(*gid);
2020 
2021     if (!h) return GRIB_INVALID_GRIB;
2022 
2023     return grib_set_double(h, key, *val);
2024 }
2025 
grib_c_get_real8_element(int * gid,char * key,int * index,double * val)2026 int grib_c_get_real8_element(int* gid, char* key, int* index, double* val)
2027 {
2028     grib_handle* h = get_handle(*gid);
2029 
2030     if (!h) return GRIB_INVALID_GRIB;
2031 
2032     return grib_get_double_element(h, key, *index, val);
2033 }
2034 
grib_c_get_real8_elements(int * gid,char * key,int * index,double * val,int * size)2035 int grib_c_get_real8_elements(int* gid, char* key, int* index, double* val, int* size)
2036 {
2037     grib_handle* h = get_handle(*gid);
2038 
2039     if (!h) return GRIB_INVALID_GRIB;
2040 
2041     return grib_get_double_elements(h, key, index, *size, val);
2042 }
2043 
grib_c_find_nearest_four_single(int * gid,int * is_lsm,double * inlat,double * inlon,double * outlats,double * outlons,double * values,double * distances,int * indexes)2044 int grib_c_find_nearest_four_single(int* gid, int* is_lsm,
2045                                     double* inlat, double* inlon,
2046                                     double* outlats, double* outlons,
2047                                     double* values, double* distances,
2048                                     int* indexes)
2049 {
2050     grib_nearest* nearest = NULL;
2051     int err = 0, result = 0;
2052     unsigned long flags = 0;
2053     size_t len          = 4;
2054     grib_handle* h      = get_handle(*gid);
2055 
2056     if (!h) return GRIB_INVALID_GRIB;
2057 
2058     nearest = grib_nearest_new(h, &err);
2059     if (err != GRIB_SUCCESS) return err;
2060 
2061     result = grib_nearest_find(nearest, h, *inlat, *inlon,
2062                                flags, outlats, outlons, values, distances, indexes, &len);
2063     grib_nearest_delete(nearest);
2064     return result;
2065 }
2066 
grib_c_find_nearest_single(int * gid,int * is_lsm,double * inlats,double * inlons,double * outlats,double * outlons,double * values,double * distances,int * indexes)2067 int grib_c_find_nearest_single(int* gid, int* is_lsm,
2068                                double* inlats, double* inlons,
2069                                double* outlats, double* outlons,
2070                                double* values, double* distances,
2071                                int* indexes)
2072 {
2073     grib_handle* h = get_handle(*gid);
2074 
2075     if (!h) return GRIB_INVALID_GRIB;
2076 
2077     return grib_nearest_find_multiple(h, *is_lsm,
2078                                       inlats, inlons, 1, outlats, outlons,
2079                                       values, distances, indexes);
2080 }
2081 
grib_c_find_nearest_multiple(int * gid,int * is_lsm,double * inlats,double * inlons,double * outlats,double * outlons,double * values,double * distances,int * indexes,int * npoints)2082 int grib_c_find_nearest_multiple(int* gid, int* is_lsm,
2083                                  double* inlats, double* inlons,
2084                                  double* outlats, double* outlons,
2085                                  double* values, double* distances,
2086                                  int* indexes, int* npoints)
2087 {
2088     grib_handle* h = get_handle(*gid);
2089 
2090     if (!h) return GRIB_INVALID_GRIB;
2091 
2092     return grib_nearest_find_multiple(h, *is_lsm,
2093                                       inlats, inlons, *npoints, outlats, outlons,
2094                                       values, distances, indexes);
2095 }
2096 
grib_c_get_real8_array(int * gid,char * key,double * val,int * size)2097 int grib_c_get_real8_array(int* gid, char* key, double* val, int* size)
2098 {
2099     grib_handle* h = get_handle(*gid);
2100     int err        = GRIB_SUCCESS;
2101     size_t lsize   = *size;
2102 
2103     if (!h) {
2104         return GRIB_INVALID_GRIB;
2105     }
2106     else {
2107         err   = grib_get_double_array(h, key, val, &lsize);
2108         *size = lsize;
2109         return err;
2110     }
2111 }
2112 
grib_c_set_real8_array(int * gid,char * key,double * val,int * size)2113 int grib_c_set_real8_array(int* gid, char* key, double* val, int* size)
2114 {
2115     grib_handle* h = get_handle(*gid);
2116 
2117     size_t lsize = *size;
2118 
2119     if (!h) return GRIB_INVALID_GRIB;
2120 
2121     return grib_set_double_array(h, key, val, lsize);
2122 }
2123 
grib_c_set_double_array(int * gid,char * key,double * val,int * size)2124 int grib_c_set_double_array(int* gid, char* key, double* val, int* size)
2125 {
2126     grib_handle* h = get_handle(*gid);
2127 
2128     size_t lsize = *size;
2129 
2130     if (!h) return GRIB_INVALID_GRIB;
2131 
2132     return grib_set_double_array(h, key, val, lsize);
2133 }
2134 
grib_c_get_string(int * gid,char * key,char * val,size_t * lsize)2135 int grib_c_get_string(int* gid, char* key, char* val, size_t* lsize)
2136 {
2137     grib_handle* h = get_handle(*gid);
2138     int err        = GRIB_SUCCESS;
2139 
2140     if (!h) return GRIB_INVALID_GRIB;
2141 
2142     err = grib_get_string(h, key, val, lsize);
2143 
2144     return err;
2145 }
2146 
grib_c_get_string_array(int * gid,char * key,char ** val,size_t * lsize)2147 int grib_c_get_string_array(int* gid, char* key, char** val, size_t* lsize)
2148 {
2149     grib_handle* h = get_handle(*gid);
2150     int err        = GRIB_SUCCESS;
2151 
2152     if (!h) return GRIB_INVALID_GRIB;
2153 
2154     err = grib_get_string_array(h, key, val, lsize);
2155 
2156     return err;
2157 }
2158 
grib_c_set_string(int * gid,char * key,char * val,int len2)2159 int grib_c_set_string(int* gid, char* key, char* val, int len2)
2160 {
2161     grib_handle* h = get_handle(*gid);
2162 
2163     size_t lsize = len2;
2164 
2165     if (!h) return GRIB_INVALID_GRIB;
2166 
2167     return grib_set_string(h, key, val, &lsize);
2168 }
2169 
grib_c_set_string_array(int * gid,char * key,const char ** val)2170 int grib_c_set_string_array(int* gid, char* key, const char** val)
2171 {
2172     grib_handle* h = get_handle(*gid);
2173     int err        = GRIB_SUCCESS;
2174     size_t lsize   = 0;
2175 
2176     if (!h) return GRIB_INVALID_GRIB;
2177 
2178     /* Note: The array passed in will have its final entry as NULL */
2179     /* so to find its size we just iterate thru it. */
2180     /* See typemap for char** in swig interface file */
2181     while (val[lsize]) {
2182         ++lsize;
2183     }
2184     err = grib_set_string_array(h, key, val, lsize);
2185     return err;
2186 }
2187 
grib_c_get_data_real4(int * gid,float * lats,float * lons,float * values,size_t * size)2188 int grib_c_get_data_real4(int* gid, float* lats, float* lons, float* values, size_t* size)
2189 {
2190     grib_handle* h = get_handle(*gid);
2191     int err        = GRIB_SUCCESS;
2192     double *lat8 = NULL, *lon8 = NULL, *val8 = NULL;
2193     size_t i = 0;
2194 
2195     if (!h) return GRIB_INVALID_GRIB;
2196 
2197     val8 = grib_context_malloc(h->context, (*size) * (sizeof(double)));
2198     if (!val8) return GRIB_OUT_OF_MEMORY;
2199     lon8 = grib_context_malloc(h->context, (*size) * (sizeof(double)));
2200     if (!lon8) return GRIB_OUT_OF_MEMORY;
2201     lat8 = grib_context_malloc(h->context, (*size) * (sizeof(double)));
2202     if (!lat8) return GRIB_OUT_OF_MEMORY;
2203 
2204     err = grib_get_data(h, lat8, lon8, val8);
2205 
2206     for (i = 0; i < *size; i++) {
2207         values[i] = val8[i];
2208         lats[i]   = lat8[i];
2209         lons[i]   = lon8[i];
2210     }
2211 
2212     grib_context_free(h->context, val8);
2213     grib_context_free(h->context, lat8);
2214     grib_context_free(h->context, lon8);
2215 
2216     return err;
2217 }
2218 /*
2219 int grib_c_get_data_real8(int* gid,double* lats, double* lons,double* values,size_t* size)
2220 {
2221     grib_handle *h = get_handle(*gid);
2222     return grib_get_data(h,lats,lons,values);
2223 }
2224 */
grib_c_copy_message(int * gid,void * mess,size_t * len)2225 int grib_c_copy_message(int* gid, void* mess, size_t* len)
2226 {
2227     grib_handle* h = get_handle(*gid);
2228     if (!h)
2229         return GRIB_INVALID_GRIB;
2230 
2231     if (*len < h->buffer->ulength) {
2232         grib_context_log(h->context, GRIB_LOG_ERROR, "grib_copy_message: buffer=%ld message size=%ld", *len, h->buffer->ulength);
2233         return GRIB_BUFFER_TOO_SMALL;
2234     }
2235 
2236     memcpy(mess, h->buffer->data, h->buffer->ulength);
2237     *len = h->buffer->ulength;
2238     return GRIB_SUCCESS;
2239 }
2240 
grib_c_bufr_copy_data(int * msgid_src,int * msgid_dst)2241 int grib_c_bufr_copy_data(int* msgid_src, int* msgid_dst)
2242 {
2243     int err           = 0;
2244     grib_handle* src  = get_handle(*msgid_src);
2245     grib_handle* dest = get_handle(*msgid_dst);
2246     if (!src || !dest) {
2247         return GRIB_INVALID_GRIB;
2248     }
2249 
2250     err = codes_bufr_copy_data(src, dest);
2251     return err;
2252 }
2253 
grib_c_check(int * err,char * call,char * str)2254 void grib_c_check(int* err, char* call, char* str)
2255 {
2256     grib_context* c = grib_context_get_default();
2257     if (*err == GRIB_SUCCESS || *err == GRIB_END_OF_FILE) return;
2258     grib_context_log(c, GRIB_LOG_ERROR, "%s: %s %s",
2259                      call, str, grib_get_error_message(*err));
2260     exit(*err);
2261 }
2262 
grib_c_write(int * gid,FILE * f)2263 int grib_c_write(int* gid, FILE* f)
2264 {
2265     grib_handle* h   = get_handle(*gid);
2266     const void* mess = NULL;
2267     size_t mess_len  = 0;
2268 
2269     if (!f) return GRIB_INVALID_FILE;
2270     if (!h) return GRIB_INVALID_GRIB;
2271 
2272     grib_get_message(h, &mess, &mess_len);
2273     if (fwrite(mess, 1, mess_len, f) != mess_len) {
2274         perror("grib_write");
2275         return GRIB_IO_PROBLEM;
2276     }
2277 
2278     return GRIB_SUCCESS;
2279 }
2280 
grib_c_multi_new(int * mgid)2281 int grib_c_multi_new(int* mgid)
2282 {
2283     grib_multi_handle* mh = grib_multi_handle_new(0);
2284     if (!mh) return GRIB_INVALID_GRIB;
2285     push_multi_handle(mh, mgid);
2286     return GRIB_SUCCESS;
2287 }
2288 
grib_c_multi_write(int * gid,FILE * f)2289 int grib_c_multi_write(int* gid, FILE* f)
2290 {
2291     grib_multi_handle* h = get_multi_handle(*gid);
2292 
2293     if (!f) return GRIB_INVALID_FILE;
2294     if (!h) return GRIB_INVALID_GRIB;
2295 
2296     return grib_multi_handle_write(h, f);
2297 }
2298 
grib_c_multi_append(int * ingid,int * sec,int * mgid)2299 int grib_c_multi_append(int* ingid, int* sec, int* mgid)
2300 {
2301     grib_handle* h        = get_handle(*ingid);
2302     grib_multi_handle* mh = get_multi_handle(*mgid);
2303 
2304     if (!h) return GRIB_INVALID_GRIB;
2305 
2306     if (!mh) {
2307         mh = grib_multi_handle_new(h->context);
2308         push_multi_handle(mh, mgid);
2309     }
2310 
2311     return grib_multi_handle_append(h, *sec, mh);
2312 }
2313 
grib_c_get_native_type(int * gid,char * key,int * type)2314 int grib_c_get_native_type(int* gid, char* key, int* type)
2315 {
2316     grib_handle* h = get_handle(*gid);
2317 
2318     if (!h) return GRIB_INVALID_GRIB;
2319 
2320     return grib_get_native_type(h, key, type);
2321 }
2322 
grib_c_index_write(int * gid,char * file)2323 int grib_c_index_write(int* gid, char* file)
2324 {
2325     grib_index* i = get_index(*gid);
2326     int err       = GRIB_SUCCESS;
2327 
2328     if (!i) {
2329         return GRIB_INVALID_GRIB;
2330     }
2331     else {
2332         err = grib_index_write(i, file);
2333         return err;
2334     }
2335 }
2336 
grib_c_index_read(char * file,int * gid)2337 int grib_c_index_read(char* file, int* gid)
2338 {
2339     int err       = 0;
2340     grib_index* i = NULL;
2341 
2342     if (*file) {
2343         i = grib_index_read(0, file, &err);
2344         if (i) {
2345             push_index(i, gid);
2346             return GRIB_SUCCESS;
2347         }
2348         else {
2349             *gid = -1;
2350             return GRIB_END_OF_FILE;
2351         }
2352     }
2353 
2354     *gid = -1;
2355     return GRIB_INVALID_FILE;
2356 }
2357 
no_fail_on_wrong_length(int flag)2358 void no_fail_on_wrong_length(int flag)
2359 {
2360     grib_context* c = grib_context_get_default();
2361     int value;
2362     assert(c != NULL);
2363     value                      = (flag != 0) ? 1 : 0;
2364     c->no_fail_on_wrong_length = value;
2365 }
2366 
grib_c_gts_header_on(void)2367 void grib_c_gts_header_on(void)
2368 {
2369     grib_context* c = grib_context_get_default();
2370     assert(c != NULL);
2371     grib_gts_header_on(c);
2372 }
2373 
grib_c_gts_header_off(void)2374 void grib_c_gts_header_off(void)
2375 {
2376     grib_context* c = grib_context_get_default();
2377     assert(c != NULL);
2378     grib_gts_header_off(c);
2379 }
2380 
grib_c_get_api_version(void)2381 long grib_c_get_api_version(void)
2382 {
2383     return grib_get_api_version();
2384 }
2385 
grib_c_get_message(int * gid,const void ** msg,size_t * size)2386 int grib_c_get_message(int* gid, const void** msg, size_t* size)
2387 {
2388     grib_handle* h = get_handle(*gid);
2389     return grib_get_message(h, msg, size);
2390 }
2391 
grib_c_set_definitions_path(const char * path)2392 void grib_c_set_definitions_path(const char* path)
2393 {
2394     grib_context* c = grib_context_get_default();
2395     grib_context_set_definitions_path(c, path);
2396 }
2397 
grib_c_set_samples_path(const char * path)2398 void grib_c_set_samples_path(const char* path)
2399 {
2400     grib_context* c = grib_context_get_default();
2401     grib_context_set_samples_path(c, path);
2402 }
2403 
2404 
codes_c_bufr_multi_element_constant_arrays_on(void)2405 int codes_c_bufr_multi_element_constant_arrays_on(void)
2406 {
2407     codes_bufr_multi_element_constant_arrays_on(NULL);
2408     return GRIB_SUCCESS;
2409 }
codes_c_bufr_multi_element_constant_arrays_off(void)2410 int codes_c_bufr_multi_element_constant_arrays_off(void)
2411 {
2412     codes_bufr_multi_element_constant_arrays_off(NULL);
2413     return GRIB_SUCCESS;
2414 }
2415