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  * Jean Baptiste Filippi - 01.11.2005
12  * Enrico Fucile                                                           *
13  ***************************************************************************/
14 #include "grib_api_internal.h"
15 #include <float.h>
16 
17 /* Note: A fast cut-down version of strcmp which does NOT return -1 */
18 /* 0 means input strings are equal and 1 means not equal */
grib_inline_strcmp(const char * a,const char * b)19 GRIB_INLINE static int grib_inline_strcmp(const char* a, const char* b)
20 {
21     if (*a != *b)
22         return 1;
23     while ((*a != 0 && *b != 0) && *(a) == *(b)) {
24         a++;
25         b++;
26     }
27     return (*a == 0 && *b == 0) ? 0 : 1;
28 }
29 
grib_set_expression(grib_handle * h,const char * name,grib_expression * e)30 int grib_set_expression(grib_handle* h, const char* name, grib_expression* e)
31 {
32     grib_accessor* a = grib_find_accessor(h, name);
33     int ret          = GRIB_SUCCESS;
34 
35     if (a) {
36         if (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
37             return GRIB_READ_ONLY;
38 
39         ret = grib_pack_expression(a, e);
40         if (ret == GRIB_SUCCESS) {
41             return grib_dependency_notify_change(a);
42         }
43         return ret;
44     }
45     return GRIB_NOT_FOUND;
46 }
47 
grib_set_expression_internal(grib_handle * h,const char * name,grib_expression * e)48 int grib_set_expression_internal(grib_handle* h, const char* name, grib_expression* e)
49 {
50     grib_accessor* a = grib_find_accessor(h, name);
51 
52     int ret = GRIB_SUCCESS;
53     if (a) {
54         ret = grib_pack_expression(a, e);
55         if (ret == GRIB_SUCCESS) {
56             return grib_dependency_notify_change(a);
57         }
58         return ret;
59     }
60     return GRIB_NOT_FOUND;
61 }
62 
grib_set_long_internal(grib_handle * h,const char * name,long val)63 int grib_set_long_internal(grib_handle* h, const char* name, long val)
64 {
65     grib_context* c  = h->context;
66     int ret          = GRIB_SUCCESS;
67     grib_accessor* a = NULL;
68     size_t l         = 1;
69 
70     a = grib_find_accessor(h, name);
71 
72     if (h->context->debug)
73         fprintf(stderr, "ECCODES DEBUG grib_set_long_internal %s=%ld\n", name, (long)val);
74 
75     if (a) {
76         ret = grib_pack_long(a, &val, &l);
77         if (ret == GRIB_SUCCESS) {
78             return grib_dependency_notify_change(a);
79         }
80 
81         grib_context_log(c, GRIB_LOG_ERROR, "unable to set %s=%ld as long (%s)",
82                          name, val, grib_get_error_message(ret));
83         return ret;
84     }
85 
86     grib_context_log(c, GRIB_LOG_ERROR, "unable to find accessor %s", name);
87     return GRIB_NOT_FOUND;
88 }
89 
grib_set_long(grib_handle * h,const char * name,long val)90 int grib_set_long(grib_handle* h, const char* name, long val)
91 {
92     int ret          = GRIB_SUCCESS;
93     grib_accessor* a = NULL;
94     size_t l         = 1;
95 
96     a = grib_find_accessor(h, name);
97 
98     if (a) {
99         if (h->context->debug) {
100             if (strcmp(name, a->name)!=0)
101                 fprintf(stderr, "ECCODES DEBUG grib_set_long %s=%ld (a->name=%s)\n", name, (long)val, a->name);
102             else
103                 fprintf(stderr, "ECCODES DEBUG grib_set_long %s=%ld\n", name, (long)val);
104         }
105 
106         if (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
107             return GRIB_READ_ONLY;
108 
109         ret = grib_pack_long(a, &val, &l);
110         if (ret == GRIB_SUCCESS)
111             return grib_dependency_notify_change(a);
112 
113         return ret;
114     }
115     return GRIB_NOT_FOUND;
116 }
117 
grib_set_double_internal(grib_handle * h,const char * name,double val)118 int grib_set_double_internal(grib_handle* h, const char* name, double val)
119 {
120     int ret          = GRIB_SUCCESS;
121     grib_accessor* a = NULL;
122     size_t l         = 1;
123 
124     a = grib_find_accessor(h, name);
125 
126     if (h->context->debug)
127         fprintf(stderr, "ECCODES DEBUG grib_set_double_internal %s=%g\n", name, val);
128 
129     if (a) {
130         ret = grib_pack_double(a, &val, &l);
131         if (ret == GRIB_SUCCESS) {
132             return grib_dependency_notify_change(a);
133         }
134 
135         grib_context_log(h->context, GRIB_LOG_ERROR, "unable to set %s=%g as double (%s)",
136                          name, val, grib_get_error_message(ret));
137         return ret;
138     }
139 
140     grib_context_log(h->context, GRIB_LOG_ERROR, "unable to find accessor %s", name);
141     return GRIB_NOT_FOUND;
142 }
143 
144 typedef struct grib_key_err grib_key_err;
145 struct grib_key_err
146 {
147     char* name;
148     int err;
149     grib_key_err* next;
150 };
151 
grib_copy_namespace(grib_handle * dest,const char * name,grib_handle * src)152 int grib_copy_namespace(grib_handle* dest, const char* name, grib_handle* src)
153 {
154     int* err = NULL;
155     int type, error_code = 0;
156     size_t len;
157     char* sval            = NULL;
158     unsigned char* uval   = NULL;
159     double* dval          = NULL;
160     long* lval            = NULL;
161     grib_key_err* key_err = NULL;
162     grib_key_err* first   = NULL;
163     int todo = 1, count = 0;
164 
165     grib_keys_iterator* iter = NULL;
166 
167     if (!dest || !src)
168         return GRIB_NULL_HANDLE;
169 
170     iter = grib_keys_iterator_new(src, 0, name);
171 
172     if (!iter) {
173         grib_context_log(src->context, GRIB_LOG_ERROR, "grib_copy_namespace: unable to get iterator for %s", name);
174         return GRIB_INTERNAL_ERROR;
175     }
176 
177     while (grib_keys_iterator_next(iter)) {
178         grib_key_err* k = (grib_key_err*)grib_context_malloc_clear(src->context, sizeof(grib_key_err));
179         k->err          = GRIB_NOT_FOUND;
180         k->name         = grib_context_strdup(src->context, grib_keys_iterator_get_name(iter));
181         if (key_err == NULL) {
182             key_err = k;
183             first   = k;
184         }
185         else {
186             key_err->next = k;
187             key_err       = key_err->next;
188         }
189     }
190 
191     count = 0;
192     todo  = 1;
193     while (todo && count < 4) {
194         grib_accessor* a = NULL;
195         key_err          = first;
196         while (key_err) {
197             char* key = key_err->name;
198             err       = &(key_err->err);
199 
200             if (*err == GRIB_SUCCESS) {
201                 key_err = key_err->next;
202                 continue;
203             }
204 
205             if ((a = grib_find_accessor(dest, key)) == NULL) {
206                 key_err->err = GRIB_NOT_FOUND;
207                 key_err      = key_err->next;
208                 continue;
209             }
210 
211             if (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) {
212                 key_err->err = GRIB_SUCCESS;
213                 key_err      = key_err->next;
214                 continue;
215             }
216 
217             if (grib_is_missing(src, key, err) && *err == 0 && (*err = grib_set_missing(dest, key))) {
218                 if (*err != GRIB_SUCCESS && *err != GRIB_NOT_FOUND)
219                     return *err;
220                 key_err = key_err->next;
221                 continue;
222             }
223 
224             if ((*err = grib_get_native_type(dest, key, &type)) != GRIB_SUCCESS) {
225                 if (*err != GRIB_SUCCESS && *err != GRIB_NOT_FOUND)
226                     return *err;
227                 key_err = key_err->next;
228                 continue;
229             }
230 
231             if ((*err = grib_get_size(src, key, &len)) != GRIB_SUCCESS)
232                 return *err;
233 
234             switch (type) {
235                 case GRIB_TYPE_STRING:
236                     len  = 512;
237                     sval = (char*)grib_context_malloc(src->context, len * sizeof(char));
238 
239                     if ((*err = grib_get_string(src, key, sval, &len)) != GRIB_SUCCESS)
240                         return *err;
241 
242                     if ((*err = grib_set_string(dest, key, sval, &len)) != GRIB_SUCCESS)
243                         return *err;
244 
245                     grib_context_free(src->context, sval);
246                     break;
247 
248                 case GRIB_TYPE_LONG:
249                     lval = (long*)grib_context_malloc(src->context, len * sizeof(long));
250 
251                     if ((*err = grib_get_long_array(src, key, lval, &len)) != GRIB_SUCCESS)
252                         return *err;
253 
254                     if ((*err = grib_set_long_array(dest, key, lval, len)) != GRIB_SUCCESS)
255                         return *err;
256 
257                     grib_context_free(src->context, lval);
258                     break;
259 
260                 case GRIB_TYPE_DOUBLE:
261                     dval = (double*)grib_context_malloc(src->context, len * sizeof(double));
262 
263                     if ((*err = grib_get_double_array(src, key, dval, &len)) != GRIB_SUCCESS)
264                         return *err;
265 
266                     if ((*err = grib_set_double_array(dest, key, dval, len)) != GRIB_SUCCESS)
267                         return *err;
268 
269                     grib_context_free(src->context, dval);
270                     break;
271 
272                 case GRIB_TYPE_BYTES:
273                     if (len == 0)
274                         len = 512;
275                     uval = (unsigned char*)grib_context_malloc(src->context, len * sizeof(unsigned char));
276 
277                     if ((*err = grib_get_bytes(src, key, uval, &len)) != GRIB_SUCCESS)
278                         return *err;
279 
280                     if ((*err = grib_get_bytes(dest, key, uval, &len)) != GRIB_SUCCESS)
281                         return *err;
282 
283                     grib_context_free(src->context, uval);
284 
285                     break;
286 
287                 default:
288                     break;
289             }
290             key_err = key_err->next;
291         }
292         count++;
293         key_err = first;
294         todo    = 0;
295         while (key_err) {
296             if (key_err->err == GRIB_NOT_FOUND) {
297                 todo = 1;
298                 break;
299             }
300             key_err = key_err->next;
301         }
302     }
303     if (err)
304         error_code = *err; /* copy the error code before cleanup */
305     grib_keys_iterator_delete(iter);
306     key_err = first;
307     while (key_err) {
308         grib_key_err* next = key_err->next;
309         grib_context_free(src->context, key_err->name);
310         grib_context_free(src->context, key_err);
311         key_err = next;
312     }
313 
314     return error_code;
315 }
316 
grib_set_double(grib_handle * h,const char * name,double val)317 int grib_set_double(grib_handle* h, const char* name, double val)
318 {
319     int ret          = GRIB_SUCCESS;
320     grib_accessor* a = NULL;
321     size_t l         = 1;
322 
323     a = grib_find_accessor(h, name);
324 
325     if (a) {
326         if (h->context->debug) {
327             if (strcmp(name, a->name)!=0)
328                 fprintf(stderr, "ECCODES DEBUG grib_set_double %s=%g (a->name=%s)\n", name, val, a->name);
329             else
330                 fprintf(stderr, "ECCODES DEBUG grib_set_double %s=%g\n", name, val);
331         }
332 
333         if (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
334             return GRIB_READ_ONLY;
335 
336         ret = grib_pack_double(a, &val, &l);
337         if (ret == GRIB_SUCCESS)
338             return grib_dependency_notify_change(a);
339 
340         return ret;
341     }
342     return GRIB_NOT_FOUND;
343 }
344 
grib_set_string_internal(grib_handle * h,const char * name,const char * val,size_t * length)345 int grib_set_string_internal(grib_handle* h, const char* name,
346                              const char* val, size_t* length)
347 {
348     int ret          = GRIB_SUCCESS;
349     grib_accessor* a = NULL;
350 
351     a = grib_find_accessor(h, name);
352 
353     if (h->context->debug)
354         fprintf(stderr, "ECCODES DEBUG grib_set_string_internal %s=%s\n", name, val);
355 
356     if (a) {
357         ret = grib_pack_string(a, val, length);
358         if (ret == GRIB_SUCCESS) {
359             return grib_dependency_notify_change(a);
360         }
361 
362         grib_context_log(h->context, GRIB_LOG_ERROR, "unable to set %s=%s as string (%s)",
363                          name, val, grib_get_error_message(ret));
364         return ret;
365     }
366 
367     grib_context_log(h->context, GRIB_LOG_ERROR, "unable to find accessor %s", name);
368     return GRIB_NOT_FOUND;
369 }
370 
grib_set_string(grib_handle * h,const char * name,const char * val,size_t * length)371 int grib_set_string(grib_handle* h, const char* name, const char* val, size_t* length)
372 {
373     int ret          = 0;
374     grib_accessor* a = NULL;
375 
376     /* Second order doesn't have a proper representation for constant fields.
377        So best not to do the change of packing type.
378        Use strncmp to catch all flavours of second order packing e.g. grid_second_order_boustrophedonic
379      */
380     if (!grib_inline_strcmp(name, "packingType") && !strncmp(val, "grid_second_order", 17)) {
381         long bitsPerValue   = 0;
382         size_t numCodedVals = 0;
383         grib_get_long(h, "bitsPerValue", &bitsPerValue);
384         if (bitsPerValue == 0) {
385             /* ECC-1219: packingType conversion from grid_ieee to grid_second_order */
386             /* Normally having a bitsPerValue of 0 means a constant field but this is
387              * not so for IEEE packing which can be non-constant but always has bitsPerValue==0!
388              */
389             char input_packing_type[100] = {0,};
390             size_t len = sizeof(input_packing_type);
391             grib_get_string(h, "packingType", input_packing_type, &len);
392             if (strcmp(input_packing_type, "grid_ieee") != 0) {
393                 /* If it's not IEEE, then bitsPerValue==0 means constant field */
394                 if (h->context->debug) {
395                     fprintf(stderr, "ECCODES DEBUG grib_set_string packingType: Constant field cannot be encoded in second order. Packing not changed\n");
396                 }
397                 return 0;
398             }
399         }
400 
401         /* GRIB-883: check if there are enough coded values */
402         ret = grib_get_size(h, "codedValues", &numCodedVals);
403         if (ret == GRIB_SUCCESS && numCodedVals < 3) {
404             if (h->context->debug) {
405                 fprintf(stderr, "ECCODES DEBUG grib_set_string packingType: not enough coded values for second order. Packing not changed\n");
406             }
407             return 0;
408         }
409     }
410 
411     a = grib_find_accessor(h, name);
412 
413     if (a) {
414         if (h->context->debug) {
415             if (strcmp(name, a->name)!=0)
416                 fprintf(stderr, "ECCODES DEBUG grib_set_string %s=|%s| (a->name=%s)\n", name, val, a->name);
417             else
418                 fprintf(stderr, "ECCODES DEBUG grib_set_string %s=|%s|\n", name, val);
419         }
420 
421         if (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
422             return GRIB_READ_ONLY;
423 
424         ret = grib_pack_string(a, val, length);
425         if (ret == GRIB_SUCCESS) {
426             return grib_dependency_notify_change(a);
427         }
428         return ret;
429     }
430     return GRIB_NOT_FOUND;
431 }
432 
grib_set_string_array(grib_handle * h,const char * name,const char ** val,size_t length)433 int grib_set_string_array(grib_handle* h, const char* name, const char** val, size_t length)
434 {
435     int ret = 0;
436     grib_accessor* a;
437 
438     a = grib_find_accessor(h, name);
439 
440     if (h->context->debug) {
441         fprintf(stderr, "ECCODES DEBUG grib_set_string_array key=%s %ld values\n", name, (long)length);
442     }
443 
444     if (a) {
445         if (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
446             return GRIB_READ_ONLY;
447 
448         ret = grib_pack_string_array(a, val, &length);
449         if (ret == GRIB_SUCCESS) {
450             return grib_dependency_notify_change(a);
451         }
452         return ret;
453     }
454     return GRIB_NOT_FOUND;
455 }
456 
grib_set_bytes_internal(grib_handle * h,const char * name,const unsigned char * val,size_t * length)457 int grib_set_bytes_internal(grib_handle* h, const char* name, const unsigned char* val, size_t* length)
458 {
459     int ret          = GRIB_SUCCESS;
460     grib_accessor* a = NULL;
461 
462     a = grib_find_accessor(h, name);
463 
464     if (a) {
465         ret = grib_pack_bytes(a, val, length);
466         if (ret == GRIB_SUCCESS) {
467             return grib_dependency_notify_change(a);
468         }
469 
470         grib_context_log(h->context, GRIB_LOG_ERROR, "unable to set %s=%ld as bytes (%s)",
471                          name, val, grib_get_error_message(ret));
472         return ret;
473     }
474 
475     grib_context_log(h->context, GRIB_LOG_ERROR, "unable to find accessor %s", name);
476     return GRIB_NOT_FOUND;
477 }
478 
grib_set_bytes(grib_handle * h,const char * name,const unsigned char * val,size_t * length)479 int grib_set_bytes(grib_handle* h, const char* name, const unsigned char* val, size_t* length)
480 {
481     int ret          = 0;
482     grib_accessor* a = grib_find_accessor(h, name);
483 
484     if (a) {
485         /* if(a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) */
486         /* return GRIB_READ_ONLY; */
487 
488         ret = grib_pack_bytes(a, val, length);
489         if (ret == GRIB_SUCCESS) {
490             return grib_dependency_notify_change(a);
491         }
492         return ret;
493     }
494     return GRIB_NOT_FOUND;
495 }
496 
grib_clear(grib_handle * h,const char * name)497 int grib_clear(grib_handle* h, const char* name)
498 {
499     int ret          = 0;
500     grib_accessor* a = NULL;
501 
502     a = grib_find_accessor(h, name);
503 
504     if (a) {
505         if (a->length == 0)
506             return 0;
507         if ((ret = grib_pack_zero(a)) != GRIB_SUCCESS)
508             grib_context_log(h->context, GRIB_LOG_ERROR, "unable to clear %s (%s)",
509                              name, grib_get_error_message(ret));
510         return ret;
511     }
512 
513     /*grib_context_log(h->context,GRIB_LOG_ERROR,"unable to find accessor %s",name);*/
514     return GRIB_NOT_FOUND;
515 }
516 
grib_set_missing_internal(grib_handle * h,const char * name)517 int grib_set_missing_internal(grib_handle* h, const char* name)
518 {
519     int ret          = 0;
520     grib_accessor* a = NULL;
521 
522     a = grib_find_accessor(h, name);
523 
524     if (a) {
525         if (a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) {
526             ret = grib_pack_missing(a);
527             if (ret == GRIB_SUCCESS)
528                 return grib_dependency_notify_change(a);
529         }
530         else
531             ret = GRIB_VALUE_CANNOT_BE_MISSING;
532 
533         grib_context_log(h->context, GRIB_LOG_ERROR, "unable to set %s=missing (%s)",
534                          name, grib_get_error_message(ret));
535         return ret;
536     }
537 
538     grib_context_log(h->context, GRIB_LOG_ERROR, "unable to find accessor %s", name);
539     return GRIB_NOT_FOUND;
540 }
541 
grib_set_missing(grib_handle * h,const char * name)542 int grib_set_missing(grib_handle* h, const char* name)
543 {
544     int ret          = 0;
545     grib_accessor* a = NULL;
546 
547     a = grib_find_accessor(h, name);
548 
549     if (a) {
550         if (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY)
551             return GRIB_READ_ONLY;
552 
553         if (a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) {
554             if (h->context->debug)
555                 fprintf(stderr, "ECCODES DEBUG grib_set_missing %s\n", name);
556 
557             ret = grib_pack_missing(a);
558             if (ret == GRIB_SUCCESS)
559                 return grib_dependency_notify_change(a);
560         }
561         else
562             ret = GRIB_VALUE_CANNOT_BE_MISSING;
563 
564         grib_context_log(h->context, GRIB_LOG_ERROR, "unable to set %s=missing (%s)",
565                          name, grib_get_error_message(ret));
566         return ret;
567     }
568 
569     grib_context_log(h->context, GRIB_LOG_ERROR, "unable to find accessor %s", name);
570     return GRIB_NOT_FOUND;
571 }
572 
grib_is_missing_long(grib_accessor * a,long x)573 int grib_is_missing_long(grib_accessor* a, long x)
574 {
575     int ret = (a == NULL || (a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING)) && (x == GRIB_MISSING_LONG) ? 1 : 0;
576     return ret;
577 }
grib_is_missing_double(grib_accessor * a,double x)578 int grib_is_missing_double(grib_accessor* a, double x)
579 {
580     int ret = (a == NULL || (a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING)) && (x == GRIB_MISSING_DOUBLE) ? 1 : 0;
581     return ret;
582 }
583 
grib_is_missing_string(grib_accessor * a,unsigned char * x,size_t len)584 int grib_is_missing_string(grib_accessor* a, unsigned char* x, size_t len)
585 {
586     /* For a string value to be missing, every character has to be */
587     /* all 1's (i.e. 0xFF) */
588     /* Note: An empty string is also classified as missing */
589     int ret;
590     size_t i = 0;
591 
592     if (len == 0)
593         return 1; /* empty string */
594     ret = 1;
595     for (i = 0; i < len; i++) {
596         if (x[i] != 0xFF) {
597             ret = 0;
598             break;
599         }
600     }
601 
602     ret = (a == NULL || ((a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING) && ret == 1)) ? 1 : 0;
603     return ret;
604 }
605 
grib_accessor_is_missing(grib_accessor * a,int * err)606 int grib_accessor_is_missing(grib_accessor* a, int* err)
607 {
608     *err = GRIB_SUCCESS;
609     if (a) {
610         if (a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING)
611             return grib_is_missing_internal(a);
612         else
613             return 0;
614     }
615     else {
616         *err = GRIB_NOT_FOUND;
617         return 1;
618     }
619 }
620 
grib_is_missing(const grib_handle * h,const char * name,int * err)621 int grib_is_missing(const grib_handle* h, const char* name, int* err)
622 {
623     grib_accessor* a = grib_find_accessor(h, name);
624     return grib_accessor_is_missing(a, err);
625 }
626 
627 /* Return true if the given key exists (is defined) in our grib message */
grib_is_defined(const grib_handle * h,const char * name)628 int grib_is_defined(const grib_handle* h, const char* name)
629 {
630     grib_accessor* a = grib_find_accessor(h, name);
631     return (a ? 1 : 0);
632 }
633 
grib_set_flag(grib_handle * h,const char * name,unsigned long flag)634 int grib_set_flag(grib_handle* h, const char* name, unsigned long flag)
635 {
636     grib_accessor* a = grib_find_accessor(h, name);
637 
638     if (!a)
639         return GRIB_NOT_FOUND;
640 
641     a->flags |= flag;
642 
643     return GRIB_SUCCESS;
644 }
645 
_grib_set_double_array_internal(grib_handle * h,grib_accessor * a,const double * val,size_t buffer_len,size_t * encoded_length,int check)646 static int _grib_set_double_array_internal(grib_handle* h, grib_accessor* a,
647                                            const double* val, size_t buffer_len, size_t* encoded_length, int check)
648 {
649     if (a) {
650         int err = _grib_set_double_array_internal(h, a->same, val, buffer_len, encoded_length, check);
651 
652         if (check && (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY))
653             return GRIB_READ_ONLY;
654 
655         if (err == GRIB_SUCCESS) {
656             size_t len = buffer_len - *encoded_length;
657             if (len) {
658                 err = grib_pack_double(a, val + *encoded_length, &len);
659                 *encoded_length += len;
660                 if (err == GRIB_SUCCESS) {
661                     /* See ECC-778 */
662                     return _grib_dependency_notify_change(h, a);
663                 }
664             }
665             else {
666                 grib_get_size(h, a->name, encoded_length);
667                 err = GRIB_WRONG_ARRAY_SIZE;
668             }
669         }
670 
671         return err;
672     }
673     else {
674         return GRIB_SUCCESS;
675     }
676 }
677 
_grib_set_double_array(grib_handle * h,const char * name,const double * val,size_t length,int check)678 static int _grib_set_double_array(grib_handle* h, const char* name,
679                                   const double* val, size_t length, int check)
680 {
681     size_t encoded   = 0;
682     grib_accessor* a = grib_find_accessor(h, name);
683     int err          = 0;
684 
685     if (!a)
686         return GRIB_NOT_FOUND;
687     if (name[0] == '/' || name[0] == '#') {
688         if (check && (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY))
689             return GRIB_READ_ONLY;
690         err     = grib_pack_double(a, val, &length);
691         encoded = length;
692     }
693     else
694         err = _grib_set_double_array_internal(h, a, val, length, &encoded, check);
695 
696     if (err == GRIB_SUCCESS && length > encoded)
697         err = GRIB_ARRAY_TOO_SMALL;
698 
699     if (err == GRIB_SUCCESS)
700         return _grib_dependency_notify_change(h, a); /* See ECC-778 */
701 
702     return err;
703 }
704 
grib_set_double_array_internal(grib_handle * h,const char * name,const double * val,size_t length)705 int grib_set_double_array_internal(grib_handle* h, const char* name, const double* val, size_t length)
706 {
707     int ret = 0;
708 
709     if (h->context->debug)
710         fprintf(stderr, "ECCODES DEBUG grib_set_double_array_internal key=%s %ld values\n", name, (long)length);
711 
712     if (length == 0) {
713         grib_accessor* a = grib_find_accessor(h, name);
714         ret              = grib_pack_double(a, val, &length);
715     }
716     else {
717         ret = _grib_set_double_array(h, name, val, length, 0);
718     }
719 
720     if (ret != GRIB_SUCCESS)
721         grib_context_log(h->context, GRIB_LOG_ERROR, "unable to set double array %s (%s)",
722                          name, grib_get_error_message(ret));
723     /*if (h->context->debug) fprintf(stderr,"ECCODES DEBUG grib_set_double_array_internal key=%s --DONE\n",name);*/
724     return ret;
725 }
726 
__grib_set_double_array(grib_handle * h,const char * name,const double * val,size_t length,int check)727 static int __grib_set_double_array(grib_handle* h, const char* name, const double* val, size_t length, int check)
728 {
729     double v = 0;
730     size_t i = 0;
731 
732     if (h->context->debug) {
733         size_t N = 5;
734         /*double minVal = DBL_MAX, maxVal = -DBL_MAX;*/
735         if (length <= N)
736             N = length;
737         fprintf(stderr, "ECCODES DEBUG grib_set_double_array key=%s %ld values (", name, (long)length);
738         for (i = 0; i < N; ++i)
739             fprintf(stderr, " %g,", val[i]);
740         if (N >= length) fprintf(stderr, " )\n");
741         else fprintf(stderr, " ... )\n");
742         /*
743         * if (N >= length)
744         *    fprintf(stderr, " )\t");
745         * else
746         *     fprintf(stderr, " ... )\t");
747         * for (i = 0; i < length; ++i) {
748         *     if (val[i] < minVal) minVal = val[i];
749         *     if (val[i] > maxVal) maxVal = val[i];
750         * }
751         * fprintf(stderr, "min=%g, max=%g\n",minVal,maxVal);
752         */
753     }
754 
755     if (length == 0) {
756         grib_accessor* a = grib_find_accessor(h, name);
757         return grib_pack_double(a, val, &length);
758     }
759 
760     /*second order doesn't have a proper representation for constant fields
761       the best is not to do the change of packing type if the field is constant
762      */
763     if (!strcmp(name, "values") || !strcmp(name, "codedValues")) {
764         double missingValue;
765         int ret      = 0;
766         int constant = 0;
767 
768         ret = grib_get_double(h, "missingValue", &missingValue);
769         if (ret)
770             missingValue = 9999;
771 
772         v        = missingValue;
773         constant = 1;
774         for (i = 0; i < length; i++) {
775             if (val[i] != missingValue) {
776                 if (v == missingValue) {
777                     v = val[i];
778                 }
779                 else if (v != val[i]) {
780                     constant = 0;
781                     break;
782                 }
783             }
784         }
785         if (constant) {
786             char packingType[50] = {0,};
787             size_t slen = 50;
788 
789             grib_get_string(h, "packingType", packingType, &slen);
790             if (!strcmp(packingType, "grid_second_order") ||
791                 !strcmp(packingType, "grid_second_order_no_SPD") ||
792                 !strcmp(packingType, "grid_second_order_SPD1") ||
793                 !strcmp(packingType, "grid_second_order_SPD2") ||
794                 !strcmp(packingType, "grid_second_order_SPD3")) {
795                 slen = 11; /*length of 'grid_simple' */
796                 if (h->context->debug) {
797                     fprintf(stderr, "ECCODES DEBUG __grib_set_double_array: Cannot use second order packing for constant fields. Using simple packing\n");
798                 }
799                 ret = grib_set_string(h, "packingType", "grid_simple", &slen);
800                 if (ret != GRIB_SUCCESS) {
801                     if (h->context->debug) {
802                         fprintf(stderr, "ECCODES DEBUG __grib_set_double_array: could not switch to simple packing!\n");
803                     }
804                 }
805             }
806         }
807     }
808 
809     return _grib_set_double_array(h, name, val, length, check);
810 }
811 
grib_set_force_double_array(grib_handle * h,const char * name,const double * val,size_t length)812 int grib_set_force_double_array(grib_handle* h, const char* name, const double* val, size_t length)
813 {
814     /* GRIB-285: Same as grib_set_double_array but allows setting of READ-ONLY keys like codedValues */
815     /* Use with great caution!! */
816     return __grib_set_double_array(h, name, val, length, /*check=*/0);
817 }
818 
grib_set_double_array(grib_handle * h,const char * name,const double * val,size_t length)819 int grib_set_double_array(grib_handle* h, const char* name, const double* val, size_t length)
820 {
821     return __grib_set_double_array(h, name, val, length, /*check=*/1);
822 }
823 
_grib_set_long_array_internal(grib_handle * h,grib_accessor * a,const long * val,size_t buffer_len,size_t * encoded_length,int check)824 static int _grib_set_long_array_internal(grib_handle* h, grib_accessor* a, const long* val, size_t buffer_len, size_t* encoded_length, int check)
825 {
826     if (a) {
827         int err = _grib_set_long_array_internal(h, a->same, val, buffer_len, encoded_length, check);
828 
829         if (check && (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY))
830             return GRIB_READ_ONLY;
831 
832         if (err == GRIB_SUCCESS) {
833             size_t len = buffer_len - *encoded_length;
834             if (len) {
835                 err = grib_pack_long(a, val + *encoded_length, &len);
836                 *encoded_length += len;
837             }
838             else {
839                 grib_get_size(h, a->name, encoded_length);
840                 err = GRIB_WRONG_ARRAY_SIZE;
841             }
842         }
843 
844         return err;
845     }
846     else {
847         return GRIB_SUCCESS;
848     }
849 }
850 
_grib_set_long_array(grib_handle * h,const char * name,const long * val,size_t length,int check)851 static int _grib_set_long_array(grib_handle* h, const char* name, const long* val, size_t length, int check)
852 {
853     size_t encoded   = 0;
854     grib_accessor* a = grib_find_accessor(h, name);
855     int err          = 0;
856 
857     if (!a)
858         return GRIB_NOT_FOUND;
859 
860     if (h->context->debug) {
861         size_t i = 0;
862         size_t N = 5;
863         if (length <= N)
864             N = length;
865         fprintf(stderr, "ECCODES DEBUG _grib_set_long_array key=%s %ld values (", name, (long)length);
866         for (i = 0; i < N; ++i)
867             fprintf(stderr, " %ld,", val[i]);
868         if (N >= length)
869             fprintf(stderr, " )\n");
870         else
871             fprintf(stderr, " ... )\n");
872     }
873 
874     if (name[0] == '/' || name[0] == '#') {
875         if (check && (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY))
876             return GRIB_READ_ONLY;
877         err     = grib_pack_long(a, val, &length);
878         encoded = length;
879     }
880     else
881         err = _grib_set_long_array_internal(h, a, val, length, &encoded, check);
882 
883     if (err == GRIB_SUCCESS && length > encoded)
884         err = GRIB_ARRAY_TOO_SMALL;
885 
886     if (err == GRIB_SUCCESS)
887         return grib_dependency_notify_change(a);
888 
889     return err;
890 }
891 
grib_set_long_array_internal(grib_handle * h,const char * name,const long * val,size_t length)892 int grib_set_long_array_internal(grib_handle* h, const char* name, const long* val, size_t length)
893 {
894     int ret = _grib_set_long_array(h, name, val, length, 0);
895     if (ret != GRIB_SUCCESS)
896         grib_context_log(h->context, GRIB_LOG_ERROR, "unable to set long array %s (%s)",
897                          name, grib_get_error_message(ret));
898     return ret;
899 }
900 
grib_set_long_array(grib_handle * h,const char * name,const long * val,size_t length)901 int grib_set_long_array(grib_handle* h, const char* name, const long* val, size_t length)
902 {
903     return _grib_set_long_array(h, name, val, length, 1);
904 }
905 
grib_get_long_internal(grib_handle * h,const char * name,long * val)906 int grib_get_long_internal(grib_handle* h, const char* name, long* val)
907 {
908     int ret = grib_get_long(h, name, val);
909 
910     if (ret != GRIB_SUCCESS) {
911         grib_context_log(h->context, GRIB_LOG_ERROR,
912                          "unable to get %s as long (%s)",
913                          name, grib_get_error_message(ret));
914     }
915 
916     return ret;
917 }
918 
grib_is_in_dump(grib_handle * h,const char * name)919 int grib_is_in_dump(grib_handle* h, const char* name)
920 {
921     grib_accessor* a = grib_find_accessor(h, name);
922     if (a != NULL && (a->flags & GRIB_ACCESSOR_FLAG_DUMP))
923         return 1;
924     else
925         return 0;
926 }
927 
grib_attributes_count(grib_accessor * a,size_t * size)928 int grib_attributes_count(grib_accessor* a, size_t* size)
929 {
930     if (a) {
931         *size = 0;
932         while (a->attributes[*size] != NULL) {
933             (*size)++;
934         }
935         return GRIB_SUCCESS;
936     }
937 
938     return GRIB_NOT_FOUND;
939 }
940 
grib_get_long(const grib_handle * h,const char * name,long * val)941 int grib_get_long(const grib_handle* h, const char* name, long* val)
942 {
943     size_t length           = 1;
944     grib_accessor* a        = NULL;
945     grib_accessors_list* al = NULL;
946     int ret                 = 0;
947 
948     if (name[0] == '/') {
949         al = grib_find_accessors_list(h, name);
950         if (!al)
951             return GRIB_NOT_FOUND;
952         ret = grib_unpack_long(al->accessor, val, &length);
953         grib_context_free(h->context, al);
954     }
955     else {
956         a = grib_find_accessor(h, name);
957         if (!a)
958             return GRIB_NOT_FOUND;
959         ret = grib_unpack_long(a, val, &length);
960     }
961     return ret;
962 }
963 
grib_get_double_internal(grib_handle * h,const char * name,double * val)964 int grib_get_double_internal(grib_handle* h, const char* name, double* val)
965 {
966     int ret = grib_get_double(h, name, val);
967 
968     if (ret != GRIB_SUCCESS)
969         grib_context_log(h->context, GRIB_LOG_ERROR,
970                          "unable to get %s as double (%s)",
971                          name, grib_get_error_message(ret));
972 
973     return ret;
974 }
975 
grib_get_double(const grib_handle * h,const char * name,double * val)976 int grib_get_double(const grib_handle* h, const char* name, double* val)
977 {
978     size_t length           = 1;
979     grib_accessor* a        = NULL;
980     grib_accessors_list* al = NULL;
981     int ret                 = 0;
982 
983     if (name[0] == '/') {
984         al = grib_find_accessors_list(h, name);
985         if (!al)
986             return GRIB_NOT_FOUND;
987         ret = grib_unpack_double(al->accessor, val, &length);
988         grib_context_free(h->context, al);
989     }
990     else {
991         a = grib_find_accessor(h, name);
992         if (!a)
993             return GRIB_NOT_FOUND;
994         ret = grib_unpack_double(a, val, &length);
995     }
996     return ret;
997 }
998 
grib_get_double_element_internal(grib_handle * h,const char * name,int i,double * val)999 int grib_get_double_element_internal(grib_handle* h, const char* name, int i, double* val)
1000 {
1001     int ret = grib_get_double_element(h, name, i, val);
1002 
1003     if (ret != GRIB_SUCCESS)
1004         grib_context_log(h->context, GRIB_LOG_ERROR,
1005                          "unable to get %s as double element (%s)",
1006                          name, grib_get_error_message(ret));
1007 
1008     return ret;
1009 }
1010 
grib_get_double_element(const grib_handle * h,const char * name,int i,double * val)1011 int grib_get_double_element(const grib_handle* h, const char* name, int i, double* val)
1012 {
1013     grib_accessor* act = grib_find_accessor(h, name);
1014 
1015     if (act) {
1016         return grib_unpack_double_element(act, i, val);
1017     }
1018     return GRIB_NOT_FOUND;
1019 }
1020 
grib_points_get_values(grib_handle * h,grib_points * points,double * val)1021 int grib_points_get_values(grib_handle* h, grib_points* points, double* val)
1022 {
1023     int i, ret;
1024     grib_accessor* a = NULL;
1025 
1026     a = grib_find_accessor(h, "values");
1027 
1028     for (i = 0; i < points->n_groups; i++) {
1029         ret = grib_unpack_double_subarray(a, val, points->group_start[i], points->group_len[i]);
1030         if (ret)
1031             return ret;
1032         val += points->group_len[i];
1033     }
1034     return GRIB_SUCCESS;
1035 }
1036 
grib_get_double_elements(const grib_handle * h,const char * name,int * index_array,long len,double * val_array)1037 int grib_get_double_elements(const grib_handle* h, const char* name, int* index_array, long len, double* val_array)
1038 {
1039     double* values = 0;
1040     int err        = 0;
1041     size_t size = 0, num_bytes = 0;
1042     long j             = 0;
1043     grib_accessor* act = NULL;
1044 
1045     act = grib_find_accessor(h, name);
1046     if (!act)
1047         return GRIB_NOT_FOUND;
1048 
1049     err = _grib_get_size(h, act, &size);
1050 
1051     if (err != GRIB_SUCCESS) {
1052         grib_context_log(h->context, GRIB_LOG_ERROR, "grib_get_double_elements: cannot get size of %s\n", name);
1053         return err;
1054     }
1055 
1056     /* Check index array has valid values */
1057     for (j = 0; j < len; j++) {
1058         const int anIndex = index_array[j];
1059         if (anIndex < 0 || anIndex >= size) {
1060             grib_context_log(h->context, GRIB_LOG_ERROR,
1061                              "grib_get_double_elements: index out of range: %d (should be between 0 and %ld)", anIndex, size - 1);
1062             return GRIB_INVALID_ARGUMENT;
1063         }
1064     }
1065 
1066     num_bytes = size * sizeof(double);
1067     values    = (double*)grib_context_malloc(h->context, num_bytes);
1068     if (!values) {
1069         grib_context_log(h->context, GRIB_LOG_ERROR, "grib_get_double_elements: unable to allocate %ld bytes\n", num_bytes);
1070         return GRIB_OUT_OF_MEMORY;
1071     }
1072 
1073     err = grib_unpack_double(act, values, &size);
1074     if (!err) {
1075         for (j = 0; j < len; j++) {
1076             val_array[j] = values[index_array[j]];
1077         }
1078     }
1079 
1080     grib_context_free(h->context, values);
1081 
1082     return err;
1083 }
1084 
grib_get_string_internal(grib_handle * h,const char * name,char * val,size_t * length)1085 int grib_get_string_internal(grib_handle* h, const char* name, char* val, size_t* length)
1086 {
1087     int ret = grib_get_string(h, name, val, length);
1088 
1089     if (ret != GRIB_SUCCESS)
1090         grib_context_log(h->context, GRIB_LOG_ERROR,
1091                          "unable to get %s as string (%s)",
1092                          name, grib_get_error_message(ret));
1093 
1094     return ret;
1095 }
1096 
grib_get_string(const grib_handle * h,const char * name,char * val,size_t * length)1097 int grib_get_string(const grib_handle* h, const char* name, char* val, size_t* length)
1098 {
1099     grib_accessor* a        = NULL;
1100     grib_accessors_list* al = NULL;
1101     int ret                 = 0;
1102 
1103     if (name[0] == '/') {
1104         al = grib_find_accessors_list(h, name);
1105         if (!al)
1106             return GRIB_NOT_FOUND;
1107         ret = grib_unpack_string(al->accessor, val, length);
1108         grib_context_free(h->context, al);
1109         return ret;
1110     }
1111     else {
1112         a = grib_find_accessor(h, name);
1113         if (!a)
1114             return GRIB_NOT_FOUND;
1115         return grib_unpack_string(a, val, length);
1116     }
1117 }
1118 
grib_get_bytes_internal(const grib_handle * h,const char * name,unsigned char * val,size_t * length)1119 int grib_get_bytes_internal(const grib_handle* h, const char* name, unsigned char* val, size_t* length)
1120 {
1121     int ret = grib_get_bytes(h, name, val, length);
1122 
1123     if (ret != GRIB_SUCCESS)
1124         grib_context_log(h->context, GRIB_LOG_ERROR,
1125                          "unable to get %s as bytes (%s)",
1126                          name, grib_get_error_message(ret));
1127 
1128     return ret;
1129 }
1130 
grib_get_bytes(const grib_handle * h,const char * name,unsigned char * val,size_t * length)1131 int grib_get_bytes(const grib_handle* h, const char* name, unsigned char* val, size_t* length)
1132 {
1133     int err            = 0;
1134     grib_accessor* act = grib_find_accessor(h, name);
1135     err                = act ? grib_unpack_bytes(act, val, length) : GRIB_NOT_FOUND;
1136     if (err)
1137         grib_context_log(h->context, GRIB_LOG_ERROR,
1138                          "grib_get_bytes %s failed %s", name, grib_get_error_message(err));
1139     return err;
1140 }
1141 
grib_get_native_type(const grib_handle * h,const char * name,int * type)1142 int grib_get_native_type(const grib_handle* h, const char* name, int* type)
1143 {
1144     grib_accessors_list* al = NULL;
1145     grib_accessor* a        = NULL;
1146     *type                   = GRIB_TYPE_UNDEFINED;
1147 
1148     DebugAssert(name != NULL && strlen(name) > 0);
1149 
1150     if (name[0] == '/') {
1151         al = grib_find_accessors_list(h, name);
1152         if (!al)
1153             return GRIB_NOT_FOUND;
1154         *type = grib_accessor_get_native_type(al->accessor);
1155         grib_context_free(h->context, al);
1156     }
1157     else {
1158         a = grib_find_accessor(h, name);
1159         if (!a)
1160             return GRIB_NOT_FOUND;
1161         *type = grib_accessor_get_native_type(a);
1162     }
1163 
1164     return GRIB_SUCCESS;
1165 }
1166 
grib_get_accessor_class_name(grib_handle * h,const char * name)1167 const char* grib_get_accessor_class_name(grib_handle* h, const char* name)
1168 {
1169     grib_accessor* act = grib_find_accessor(h, name);
1170     return act ? act->cclass->name : NULL;
1171 }
1172 
_grib_get_double_array_internal(const grib_handle * h,grib_accessor * a,double * val,size_t buffer_len,size_t * decoded_length)1173 int _grib_get_double_array_internal(const grib_handle* h, grib_accessor* a, double* val, size_t buffer_len, size_t* decoded_length)
1174 {
1175     if (a) {
1176         int err = _grib_get_double_array_internal(h, a->same, val, buffer_len, decoded_length);
1177 
1178         if (err == GRIB_SUCCESS) {
1179             size_t len = buffer_len - *decoded_length;
1180             err        = grib_unpack_double(a, val + *decoded_length, &len);
1181             *decoded_length += len;
1182         }
1183 
1184         return err;
1185     }
1186     else {
1187         return GRIB_SUCCESS;
1188     }
1189 }
1190 
grib_get_double_array_internal(const grib_handle * h,const char * name,double * val,size_t * length)1191 int grib_get_double_array_internal(const grib_handle* h, const char* name, double* val, size_t* length)
1192 {
1193     int ret = grib_get_double_array(h, name, val, length);
1194 
1195     if (ret != GRIB_SUCCESS)
1196         grib_context_log(h->context, GRIB_LOG_ERROR,
1197                          "unable to get %s as double array (%s)",
1198                          name, grib_get_error_message(ret));
1199 
1200     return ret;
1201 }
1202 
grib_get_double_array(const grib_handle * h,const char * name,double * val,size_t * length)1203 int grib_get_double_array(const grib_handle* h, const char* name, double* val, size_t* length)
1204 {
1205     size_t len              = *length;
1206     grib_accessor* a        = NULL;
1207     grib_accessors_list* al = NULL;
1208     int ret                 = 0;
1209 
1210     if (name[0] == '/') {
1211         al = grib_find_accessors_list(h, name);
1212         if (!al)
1213             return GRIB_NOT_FOUND;
1214         ret = grib_accessors_list_unpack_double(al, val, length);
1215         grib_accessors_list_delete(h->context, al);
1216         return ret;
1217     }
1218     else {
1219         a = grib_find_accessor(h, name);
1220         if (!a)
1221             return GRIB_NOT_FOUND;
1222         if (name[0] == '#') {
1223             return grib_unpack_double(a, val, length);
1224         }
1225         else {
1226             *length = 0;
1227             return _grib_get_double_array_internal(h, a, val, len, length);
1228         }
1229     }
1230 }
1231 
_grib_get_string_length(grib_accessor * a,size_t * size)1232 int _grib_get_string_length(grib_accessor* a, size_t* size)
1233 {
1234     size_t s = 0;
1235 
1236     *size = 0;
1237     while (a) {
1238         s = grib_string_length(a);
1239         if (s > *size)
1240             *size = s;
1241         a = a->same;
1242     }
1243     (*size) += 1;
1244 
1245     return GRIB_SUCCESS;
1246 }
1247 
grib_get_string_length(const grib_handle * h,const char * name,size_t * size)1248 int grib_get_string_length(const grib_handle* h, const char* name, size_t* size)
1249 {
1250     grib_accessor* a        = NULL;
1251     grib_accessors_list* al = NULL;
1252     int ret                 = 0;
1253 
1254     if (name[0] == '/') {
1255         al = grib_find_accessors_list(h, name);
1256         if (!al)
1257             return GRIB_NOT_FOUND;
1258         ret = _grib_get_string_length(al->accessor, size);
1259         grib_context_free(h->context, al);
1260         return ret;
1261     }
1262     else {
1263         a = grib_find_accessor(h, name);
1264         if (!a)
1265             return GRIB_NOT_FOUND;
1266         return _grib_get_string_length(a, size);
1267     }
1268 }
1269 
_grib_get_size(const grib_handle * h,grib_accessor * a,size_t * size)1270 int _grib_get_size(const grib_handle* h, grib_accessor* a, size_t* size)
1271 {
1272     long count = 0;
1273     int err    = 0;
1274 
1275     if (!a)
1276         return GRIB_NOT_FOUND;
1277 
1278     *size = 0;
1279     while (a) {
1280         if (err == 0) {
1281             err = grib_value_count(a, &count);
1282             if (err)
1283                 return err;
1284             *size += count;
1285         }
1286         a = a->same;
1287     }
1288     return GRIB_SUCCESS;
1289 }
1290 
grib_get_size(const grib_handle * ch,const char * name,size_t * size)1291 int grib_get_size(const grib_handle* ch, const char* name, size_t* size)
1292 {
1293     grib_handle* h          = (grib_handle*)ch;
1294     grib_accessor* a        = NULL;
1295     grib_accessors_list* al = NULL;
1296     int ret                 = 0;
1297     *size                   = 0;
1298 
1299     if (name[0] == '/') {
1300         al = grib_find_accessors_list(h, name);
1301         if (!al)
1302             return GRIB_NOT_FOUND;
1303         ret = grib_accessors_list_value_count(al, size);
1304         grib_accessors_list_delete(h->context, al);
1305         return ret;
1306     }
1307     else {
1308         a = grib_find_accessor(h, name);
1309         if (!a)
1310             return GRIB_NOT_FOUND;
1311         if (name[0] == '#') {
1312             long count = *size;
1313             ret        = grib_value_count(a, &count);
1314             *size      = count;
1315             return ret;
1316         }
1317         else
1318             return _grib_get_size(h, a, size);
1319     }
1320 }
1321 
grib_get_length(const grib_handle * h,const char * name,size_t * length)1322 int grib_get_length(const grib_handle* h, const char* name, size_t* length)
1323 {
1324     return grib_get_string_length(h, name, length);
1325 }
1326 
grib_get_count(grib_handle * h,const char * name,size_t * size)1327 int grib_get_count(grib_handle* h, const char* name, size_t* size)
1328 {
1329     grib_accessor* a = grib_find_accessor(h, name);
1330     if (!a)
1331         return GRIB_NOT_FOUND;
1332 
1333     *size = 0;
1334     while (a) {
1335         (*size)++;
1336         a = a->same;
1337     }
1338     return GRIB_SUCCESS;
1339 }
1340 
grib_get_offset(const grib_handle * ch,const char * key,size_t * val)1341 int grib_get_offset(const grib_handle* ch, const char* key, size_t* val)
1342 {
1343     grib_handle* h     = (grib_handle*)ch;
1344     grib_accessor* act = grib_find_accessor(h, key);
1345     if (act) {
1346         *val = (size_t)grib_byte_offset(act);
1347         return GRIB_SUCCESS;
1348     }
1349     return GRIB_NOT_FOUND;
1350 }
1351 
_grib_get_string_array_internal(const grib_handle * h,grib_accessor * a,char ** val,size_t buffer_len,size_t * decoded_length)1352 int _grib_get_string_array_internal(const grib_handle* h, grib_accessor* a, char** val, size_t buffer_len, size_t* decoded_length)
1353 {
1354     if (a) {
1355         int err = _grib_get_string_array_internal(h, a->same, val, buffer_len, decoded_length);
1356 
1357         if (err == GRIB_SUCCESS) {
1358             size_t len = buffer_len - *decoded_length;
1359             err        = grib_unpack_string_array(a, val + *decoded_length, &len);
1360             *decoded_length += len;
1361         }
1362 
1363         return err;
1364     }
1365     else {
1366         return GRIB_SUCCESS;
1367     }
1368 }
1369 
grib_get_string_array(const grib_handle * h,const char * name,char ** val,size_t * length)1370 int grib_get_string_array(const grib_handle* h, const char* name, char** val, size_t* length)
1371 {
1372     size_t len              = *length;
1373     grib_accessor* a        = NULL;
1374     grib_accessors_list* al = NULL;
1375     int ret                 = 0;
1376 
1377     if (name[0] == '/') {
1378         al = grib_find_accessors_list(h, name);
1379         if (!al)
1380             return GRIB_NOT_FOUND;
1381         ret = grib_accessors_list_unpack_string(al, val, length);
1382         grib_context_free(h->context, al);
1383         return ret;
1384     }
1385     else {
1386         a = grib_find_accessor(h, name);
1387         if (!a)
1388             return GRIB_NOT_FOUND;
1389         if (name[0] == '#') {
1390             return grib_unpack_string_array(a, val, length);
1391         }
1392         else {
1393             *length = 0;
1394             return _grib_get_string_array_internal(h, a, val, len, length);
1395         }
1396     }
1397 }
1398 
_grib_get_long_array_internal(const grib_handle * h,grib_accessor * a,long * val,size_t buffer_len,size_t * decoded_length)1399 int _grib_get_long_array_internal(const grib_handle* h, grib_accessor* a, long* val, size_t buffer_len, size_t* decoded_length)
1400 {
1401     if (a) {
1402         int err = _grib_get_long_array_internal(h, a->same, val, buffer_len, decoded_length);
1403 
1404         if (err == GRIB_SUCCESS) {
1405             size_t len = buffer_len - *decoded_length;
1406             err        = grib_unpack_long(a, val + *decoded_length, &len);
1407             *decoded_length += len;
1408         }
1409 
1410         return err;
1411     }
1412     else {
1413         return GRIB_SUCCESS;
1414     }
1415 }
1416 
grib_get_long_array_internal(grib_handle * h,const char * name,long * val,size_t * length)1417 int grib_get_long_array_internal(grib_handle* h, const char* name, long* val, size_t* length)
1418 {
1419     int ret = grib_get_long_array(h, name, val, length);
1420 
1421     if (ret != GRIB_SUCCESS)
1422         grib_context_log(h->context, GRIB_LOG_ERROR,
1423                          "unable to get %s as long array (%s)",
1424                          name, grib_get_error_message(ret));
1425 
1426     return ret;
1427 }
1428 
grib_get_long_array(const grib_handle * h,const char * name,long * val,size_t * length)1429 int grib_get_long_array(const grib_handle* h, const char* name, long* val, size_t* length)
1430 {
1431     size_t len              = *length;
1432     grib_accessor* a        = NULL;
1433     grib_accessors_list* al = NULL;
1434     int ret                 = 0;
1435 
1436     if (name[0] == '/') {
1437         al = grib_find_accessors_list(h, name);
1438         if (!al)
1439             return GRIB_NOT_FOUND;
1440         ret = grib_accessors_list_unpack_long(al, val, length);
1441         grib_context_free(h->context, al);
1442     }
1443     else {
1444         a = grib_find_accessor(h, name);
1445         if (!a)
1446             return GRIB_NOT_FOUND;
1447         if (name[0] == '#') {
1448             return grib_unpack_long(a, val, length);
1449         }
1450         else {
1451             *length = 0;
1452             return _grib_get_long_array_internal(h, a, val, len, length);
1453         }
1454     }
1455     return ret;
1456 }
1457 
grib_clean_key_value(grib_context * c,grib_key_value_list * kv)1458 static void grib_clean_key_value(grib_context* c, grib_key_value_list* kv)
1459 {
1460     if (kv->long_value)
1461         grib_context_free(c, kv->long_value);
1462     kv->long_value = NULL;
1463     if (kv->double_value)
1464         grib_context_free(c, kv->double_value);
1465     kv->double_value = NULL;
1466     if (kv->string_value)
1467         grib_context_free(c, kv->string_value);
1468     kv->string_value = NULL;
1469     if (kv->namespace_value)
1470         grib_key_value_list_delete(c, kv->namespace_value);
1471     kv->namespace_value = NULL;
1472     kv->error           = 0;
1473     kv->has_value       = 0;
1474     kv->size            = 0;
1475 }
1476 
grib_get_key_value(grib_handle * h,grib_key_value_list * kv)1477 static int grib_get_key_value(grib_handle* h, grib_key_value_list* kv)
1478 {
1479     int err                   = 0;
1480     size_t size               = 0;
1481     grib_keys_iterator* iter  = NULL;
1482     grib_key_value_list* list = NULL;
1483 
1484     if (kv->has_value)
1485         grib_clean_key_value(h->context, kv);
1486 
1487     err = grib_get_size(h, kv->name, &size);
1488     if (err) {
1489         kv->error = err;
1490         return err;
1491     }
1492     if (size == 0)
1493         size = 512;
1494 
1495     switch (kv->type) {
1496         case GRIB_TYPE_LONG:
1497             kv->long_value = (long*)grib_context_malloc_clear(h->context, size * sizeof(long));
1498             err            = grib_get_long_array(h, kv->name, kv->long_value, &size);
1499             kv->error      = err;
1500             break;
1501         case GRIB_TYPE_DOUBLE:
1502             kv->double_value = (double*)grib_context_malloc_clear(h->context, size * sizeof(double));
1503             err              = grib_get_double_array(h, kv->name, kv->double_value, &size);
1504             kv->error        = err;
1505             break;
1506         case GRIB_TYPE_STRING:
1507             grib_get_string_length(h, kv->name, &size);
1508             kv->string_value = (char*)grib_context_malloc_clear(h->context, size * sizeof(char));
1509             err              = grib_get_string(h, kv->name, kv->string_value, &size);
1510             kv->error        = err;
1511             break;
1512         case GRIB_TYPE_BYTES:
1513             kv->string_value = (char*)grib_context_malloc_clear(h->context, size * sizeof(char));
1514             err              = grib_get_bytes(h, kv->name, (unsigned char*)kv->string_value, &size);
1515             kv->error        = err;
1516             break;
1517         case GRIB_NAMESPACE:
1518             iter                = grib_keys_iterator_new(h, 0, kv->name);
1519             list                = (grib_key_value_list*)grib_context_malloc_clear(h->context, sizeof(grib_key_value_list));
1520             kv->namespace_value = list;
1521             while (grib_keys_iterator_next(iter)) {
1522                 list->name = grib_keys_iterator_get_name(iter);
1523                 err        = grib_get_native_type(h, list->name, &(list->type));
1524                 if (err)
1525                     return err;
1526                 err = grib_get_key_value(h, list);
1527                 if (err)
1528                     return err;
1529                 list->next = (grib_key_value_list*)grib_context_malloc_clear(h->context, sizeof(grib_key_value_list));
1530                 list       = list->next;
1531             }
1532             grib_keys_iterator_delete(iter);
1533             break;
1534 
1535         default:
1536             err = grib_get_native_type(h, kv->name, &(kv->type));
1537             if (err)
1538                 return err;
1539             err = grib_get_key_value(h, kv);
1540             break;
1541     }
1542     kv->has_value = 1;
1543     return err;
1544 }
1545 
grib_key_value_list_clone(grib_context * c,grib_key_value_list * list)1546 grib_key_value_list* grib_key_value_list_clone(grib_context* c, grib_key_value_list* list)
1547 {
1548     grib_key_value_list* next      = list;
1549     grib_key_value_list* the_clone = (grib_key_value_list*)grib_context_malloc_clear(c, sizeof(grib_key_value_list));
1550     grib_key_value_list* p         = the_clone;
1551 
1552     while (next && next->name) {
1553         p->name = grib_context_strdup(c, next->name);
1554         p->type = next->type;
1555         next    = next->next;
1556     }
1557     return the_clone;
1558 }
1559 
grib_key_value_list_delete(grib_context * c,grib_key_value_list * kvl)1560 void grib_key_value_list_delete(grib_context* c, grib_key_value_list* kvl)
1561 {
1562     grib_key_value_list* next = kvl;
1563     grib_key_value_list* p    = NULL;
1564     while (next) {
1565         p = next->next;
1566         if (next->type == GRIB_NAMESPACE)
1567             grib_key_value_list_delete(c, next->namespace_value);
1568 
1569         grib_clean_key_value(c, next);
1570         grib_context_free(c, next);
1571         next = p;
1572     }
1573 }
1574 
grib_get_key_value_list(grib_handle * h,grib_key_value_list * list)1575 int grib_get_key_value_list(grib_handle* h, grib_key_value_list* list)
1576 {
1577     int ret                  = 0;
1578     grib_key_value_list* kvl = list;
1579     while (kvl) {
1580         ret = grib_get_key_value(h, kvl);
1581         kvl = kvl->next;
1582     }
1583     return ret;
1584 }
1585 
grib_get_values(grib_handle * h,grib_values * args,size_t count)1586 int grib_get_values(grib_handle* h, grib_values* args, size_t count)
1587 {
1588     int ret = 0;
1589     int i   = 0;
1590 
1591     for (i = 0; i < count; i++) {
1592         char buff[1024] = {0,};
1593         size_t len = sizeof(buff) / sizeof(*buff);
1594 
1595         if (!args[i].name) {
1596             args[i].error = GRIB_INVALID_ARGUMENT;
1597             continue;
1598         }
1599 
1600         if (args[i].type == 0) {
1601             args[i].error = grib_get_native_type(h, args[i].name, &(args[i].type));
1602             if (args[i].error != GRIB_SUCCESS)
1603                 ret = args[i].error;
1604         }
1605 
1606         switch (args[i].type) {
1607             case GRIB_TYPE_LONG:
1608                 args[i].error = grib_get_long(h, args[i].name, &(args[i].long_value));
1609                 if (args[i].error != GRIB_SUCCESS)
1610                     ret = args[i].error;
1611                 break;
1612 
1613             case GRIB_TYPE_DOUBLE:
1614                 args[i].error = grib_get_double(h, args[i].name, &(args[i].double_value));
1615                 if (args[i].error != GRIB_SUCCESS)
1616                     ret = args[i].error;
1617                 break;
1618 
1619             case GRIB_TYPE_STRING:
1620                 args[i].error        = grib_get_string(h, args[i].name, buff, &len);
1621                 args[i].string_value = strdup(buff);
1622                 if (args[i].error != GRIB_SUCCESS)
1623                     ret = args[i].error;
1624                 break;
1625 
1626             default:
1627                 args[i].error        = grib_get_string(h, args[i].name, buff, &len);
1628                 args[i].string_value = strdup(buff);
1629                 if (args[i].error != GRIB_SUCCESS)
1630                     ret = args[i].error;
1631                 break;
1632         }
1633     }
1634 
1635     return ret;
1636 }
1637 
grib_set_values(grib_handle * h,grib_values * args,size_t count)1638 int grib_set_values(grib_handle* h, grib_values* args, size_t count)
1639 {
1640     int i, error = 0;
1641     int err = 0;
1642     size_t len;
1643     int more  = 1;
1644     int stack = h->values_stack++;
1645 
1646     Assert(h->values_stack < MAX_SET_VALUES - 1);
1647 
1648     h->values[stack]       = args;
1649     h->values_count[stack] = count;
1650 
1651     for (i = 0; i < count; i++)
1652         args[i].error = GRIB_NOT_FOUND;
1653 
1654     while (more) {
1655         more = 0;
1656         for (i = 0; i < count; i++) {
1657             if (args[i].error != GRIB_NOT_FOUND)
1658                 continue;
1659 
1660             switch (args[i].type) {
1661                 case GRIB_TYPE_LONG:
1662                     error         = grib_set_long(h, args[i].name, args[i].long_value);
1663                     args[i].error = error;
1664                     if (args[i].error == GRIB_SUCCESS)
1665                         more = 1;
1666                     break;
1667 
1668                 case GRIB_TYPE_DOUBLE:
1669                     args[i].error = grib_set_double(h, args[i].name, args[i].double_value);
1670                     if (args[i].error == GRIB_SUCCESS)
1671                         more = 1;
1672                     break;
1673 
1674                 case GRIB_TYPE_STRING:
1675                     len           = strlen(args[i].string_value);
1676                     args[i].error = grib_set_string(h, args[i].name, args[i].string_value, &len);
1677                     if (args[i].error == GRIB_SUCCESS)
1678                         more = 1;
1679                     break;
1680 
1681                 case GRIB_TYPE_MISSING:
1682                     args[i].error = grib_set_missing(h, args[i].name);
1683                     if (args[i].error == GRIB_SUCCESS)
1684                         more = 1;
1685                     break;
1686 
1687                 default:
1688                     grib_context_log(h->context, GRIB_LOG_ERROR, "grib_set_values[%d] %s invalid type %d", i, args[i].name, args[i].type);
1689                     args[i].error = GRIB_INVALID_ARGUMENT;
1690                     break;
1691             }
1692             /*if (args[i].error != GRIB_SUCCESS)
1693          grib_context_log(h->context,GRIB_LOG_ERROR,"unable to set %s (%s)",
1694                           args[i].name,grib_get_error_message(args[i].error)); */
1695         }
1696     }
1697 
1698     h->values[stack]       = NULL;
1699     h->values_count[stack] = 0;
1700 
1701     h->values_stack--;
1702 
1703     for (i = 0; i < count; i++) {
1704         if (args[i].error != GRIB_SUCCESS) {
1705             grib_context_log(h->context, GRIB_LOG_ERROR,
1706                              "grib_set_values[%d] %s (type=%s) failed: %s",
1707                              i, args[i].name, grib_get_type_name(args[i].type),
1708                              grib_get_error_message(args[i].error));
1709             err = err == GRIB_SUCCESS ? args[i].error : err;
1710         }
1711     }
1712 
1713     return err;
1714 }
1715 
grib_get_nearest_smaller_value(grib_handle * h,const char * name,double val,double * nearest)1716 int grib_get_nearest_smaller_value(grib_handle* h, const char* name,
1717                                    double val, double* nearest)
1718 {
1719     grib_accessor* act = grib_find_accessor(h, name);
1720     Assert(act);
1721     return grib_nearest_smaller_value(act, val, nearest);
1722 }
1723 
grib_print_values(grib_values * values,int count)1724 void grib_print_values(grib_values* values, int count)
1725 {
1726     int i;
1727     for (i = 0; i < count; i++) {
1728         printf("%s = ", values[i].name);
1729         switch (values[i].type) {
1730             case GRIB_TYPE_LONG:
1731                 printf("%ld", values[i].long_value);
1732                 break;
1733             case GRIB_TYPE_DOUBLE:
1734                 printf("%g", values[i].double_value);
1735                 break;
1736             case GRIB_TYPE_STRING:
1737                 printf("%s", values[i].string_value);
1738                 break;
1739         }
1740         printf("\n");
1741     }
1742 }
1743 
grib_values_check(grib_handle * h,grib_values * values,int count)1744 int grib_values_check(grib_handle* h, grib_values* values, int count)
1745 {
1746     int i = 0;
1747     long long_value;
1748     double double_value;
1749     unsigned char ubuff[1024] = {0,};
1750     char buff[1024] = {0,};
1751     size_t len = 1024;
1752 
1753     for (i = 0; i < count; i++) {
1754         if (values[i].type == 0) {
1755             values[i].error = GRIB_INVALID_TYPE;
1756             return values[i].error;
1757         }
1758 
1759         switch (values[i].type) {
1760             case GRIB_TYPE_LONG:
1761                 values[i].error = grib_get_long(h, values[i].name, &long_value);
1762                 if (values[i].error != GRIB_SUCCESS)
1763                     return values[i].error;
1764                 if (long_value != values[i].long_value) {
1765                     values[i].error = GRIB_VALUE_DIFFERENT;
1766                     return values[i].error;
1767                 }
1768                 break;
1769 
1770             case GRIB_TYPE_DOUBLE:
1771                 values[i].error = grib_get_double(h, values[i].name, &double_value);
1772                 if (values[i].error != GRIB_SUCCESS)
1773                     return values[i].error;
1774                 if (double_value != values[i].double_value) {
1775                     values[i].error = GRIB_VALUE_DIFFERENT;
1776                     return values[i].error;
1777                 }
1778                 break;
1779 
1780             case GRIB_TYPE_STRING:
1781                 values[i].error = grib_get_string(h, values[i].name, buff, &len);
1782                 if (values[i].error != GRIB_SUCCESS)
1783                     return values[i].error;
1784                 if (strcmp(values[i].string_value, buff)) {
1785                     values[i].error = GRIB_VALUE_DIFFERENT;
1786                     return values[i].error;
1787                 }
1788                 break;
1789 
1790             case GRIB_TYPE_BYTES:
1791                 values[i].error = grib_get_bytes(h, values[i].name, ubuff, &len);
1792                 if (values[i].error != GRIB_SUCCESS)
1793                     return values[i].error;
1794                 if (memcmp(values[i].string_value, ubuff, len)) {
1795                     values[i].error = GRIB_VALUE_DIFFERENT;
1796                     return values[i].error;
1797                 }
1798                 break;
1799 
1800             default:
1801                 values[i].error = GRIB_INVALID_TYPE;
1802                 return values[i].error;
1803         }
1804     }
1805 
1806     return 0;
1807 }
1808 
grib_key_equal(grib_handle * h1,grib_handle * h2,const char * key,int type,int * err)1809 int grib_key_equal(grib_handle* h1, grib_handle* h2, const char* key, int type, int* err)
1810 {
1811     double d1 = 0, d2 = 0;
1812     long l1 = 0, l2 = 0;
1813     char s1[500] = {0,};
1814     char s2[500] = {0,};
1815     size_t len1, len2;
1816 
1817     if (type != GRIB_TYPE_DOUBLE &&
1818         type != GRIB_TYPE_LONG &&
1819         type != GRIB_TYPE_STRING) {
1820         *err = grib_get_native_type(h1, key, &type);
1821     }
1822     switch (type) {
1823         case GRIB_TYPE_DOUBLE:
1824             *err = grib_get_double(h1, key, &d1);
1825             *err = grib_get_double(h2, key, &d2);
1826             if (d1 != d2)
1827                 return 0;
1828             break;
1829         case GRIB_TYPE_LONG:
1830             *err = grib_get_long(h1, key, &l1);
1831             *err = grib_get_long(h2, key, &l2);
1832             if (l1 != l2)
1833                 return 0;
1834             break;
1835         default:
1836             len1 = sizeof(s1) / sizeof(*s1);
1837             len2 = sizeof(s2) / sizeof(*s2);
1838             *err = grib_get_string(h1, key, s1, &len1);
1839             *err = grib_get_string(h2, key, s2, &len2);
1840             if (grib_inline_strcmp(s1, s2))
1841                 return 0;
1842             break;
1843     }
1844     return 1;
1845 }
1846 
codes_copy_key(grib_handle * h1,grib_handle * h2,const char * key,int type)1847 int codes_copy_key(grib_handle* h1, grib_handle* h2, const char* key, int type)
1848 {
1849     double d;
1850     double* ad;
1851     long l;
1852     long* al;
1853     char* s     = 0;
1854     char** as   = 0;
1855     size_t len1 = 0, len = 0;
1856     int err = 0;
1857 
1858     if (type != GRIB_TYPE_DOUBLE &&
1859         type != GRIB_TYPE_LONG &&
1860         type != GRIB_TYPE_STRING) {
1861         err = grib_get_native_type(h1, key, &type);
1862         if (err)
1863             return err;
1864     }
1865 
1866     err = grib_get_size(h1, key, &len1);
1867     if (err)
1868         return err;
1869 
1870     switch (type) {
1871         case GRIB_TYPE_DOUBLE:
1872             if (len1 == 1) {
1873                 err = grib_get_double(h1, key, &d);
1874                 if (err)
1875                     return err;
1876                 grib_context_log(h1->context, GRIB_LOG_DEBUG, "codes_copy_key double: %s=%g\n", key, d);
1877                 err = grib_set_double(h2, key, d);
1878                 return err;
1879             }
1880             else {
1881                 ad  = (double*)grib_context_malloc_clear(h1->context, len1 * sizeof(double));
1882                 err = grib_get_double_array(h1, key, ad, &len1);
1883                 if (err)
1884                     return err;
1885                 err = grib_set_double_array(h2, key, ad, len1);
1886                 grib_context_free(h1->context, ad);
1887                 return err;
1888             }
1889             break;
1890         case GRIB_TYPE_LONG:
1891             if (len1 == 1) {
1892                 err = grib_get_long(h1, key, &l);
1893                 if (err)
1894                     return err;
1895                 grib_context_log(h1->context, GRIB_LOG_DEBUG, "codes_copy_key long: %s=%ld\n", key, l);
1896                 err = grib_set_long(h2, key, l);
1897                 return err;
1898             }
1899             else {
1900                 al  = (long*)grib_context_malloc_clear(h1->context, len1 * sizeof(long));
1901                 err = grib_get_long_array(h1, key, al, &len1);
1902                 if (err)
1903                     return err;
1904                 err = grib_set_long_array(h2, key, al, len1);
1905                 grib_context_free(h1->context, al);
1906                 return err;
1907             }
1908             break;
1909         case GRIB_TYPE_STRING:
1910             err = grib_get_string_length(h1, key, &len);
1911             if (err)
1912                 return err;
1913             if (len1 == 1) {
1914                 s   = (char*)grib_context_malloc_clear(h1->context, len);
1915                 err = grib_get_string(h1, key, s, &len);
1916                 if (err)
1917                     return err;
1918                 grib_context_log(h1->context, GRIB_LOG_DEBUG, "codes_copy_key str: %s=%s\n", key, s);
1919                 err = grib_set_string(h2, key, s, &len);
1920                 grib_context_free(h1->context, s);
1921                 return err;
1922             }
1923             else {
1924                 as  = (char**)grib_context_malloc_clear(h1->context, len1 * sizeof(char*));
1925                 err = grib_get_string_array(h1, key, as, &len1);
1926                 if (err)
1927                     return err;
1928                 err = grib_set_string_array(h2, key, (const char**)as, len1);
1929                 return err;
1930             }
1931             break;
1932         default:
1933             return GRIB_INVALID_TYPE;
1934     }
1935 }
1936