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