1 /*
2  * (C) Copyright 2005- ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  *
7  * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
8  * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
9  */
10 
11 /*****************************************
12  *  Enrico Fucile
13  ****************************************/
14 
15 #include "grib_api_internal.h"
16 
17 /*
18    This is used by make_class.pl
19 
20    START_CLASS_DEF
21    CLASS      = accessor
22    SUPER      = grib_accessor_class_gen
23    IMPLEMENTS = init;dump
24    IMPLEMENTS = unpack_string;unpack_string_array;unpack_long; unpack_double
25    IMPLEMENTS = unpack_double_element ; is_missing
26    IMPLEMENTS = pack_long; pack_double ; pack_string_array; pack_string; pack_missing
27    IMPLEMENTS = value_count; get_native_type; make_clone; destroy
28    MEMBERS    = long index
29    MEMBERS    = int type
30    MEMBERS    = long compressedData
31    MEMBERS    = long subsetNumber
32    MEMBERS    = long numberOfSubsets
33    MEMBERS    = bufr_descriptors_array* descriptors
34    MEMBERS    = grib_vdarray* numericValues
35    MEMBERS    = grib_vsarray* stringValues
36    MEMBERS    = grib_viarray* elementsDescriptorsIndex
37    MEMBERS    = char* cname
38 
39    END_CLASS_DEF
40 
41  */
42 
43 /* START_CLASS_IMP */
44 
45 /*
46 
47 Don't edit anything between START_CLASS_IMP and END_CLASS_IMP
48 Instead edit values between START_CLASS_DEF and END_CLASS_DEF
49 or edit "accessor.class" and rerun ./make_class.pl
50 
51 */
52 
53 static int get_native_type(grib_accessor*);
54 static int pack_missing(grib_accessor*);
55 static int is_missing(grib_accessor*);
56 static int pack_double(grib_accessor*, const double* val, size_t* len);
57 static int pack_long(grib_accessor*, const long* val, size_t* len);
58 static int pack_string(grib_accessor*, const char*, size_t* len);
59 static int pack_string_array(grib_accessor*, const char**, size_t* len);
60 static int unpack_double(grib_accessor*, double* val, size_t* len);
61 static int unpack_long(grib_accessor*, long* val, size_t* len);
62 static int unpack_string(grib_accessor*, char*, size_t* len);
63 static int unpack_string_array(grib_accessor*, char**, size_t* len);
64 static int value_count(grib_accessor*, long*);
65 static void destroy(grib_context*, grib_accessor*);
66 static void dump(grib_accessor*, grib_dumper*);
67 static void init(grib_accessor*, const long, grib_arguments*);
68 static void init_class(grib_accessor_class*);
69 static int unpack_double_element(grib_accessor*, size_t i, double* val);
70 static grib_accessor* make_clone(grib_accessor*, grib_section*, int*);
71 
72 typedef struct grib_accessor_bufr_data_element
73 {
74     grib_accessor att;
75     /* Members defined in gen */
76     /* Members defined in bufr_data_element */
77     long index;
78     int type;
79     long compressedData;
80     long subsetNumber;
81     long numberOfSubsets;
82     bufr_descriptors_array* descriptors;
83     grib_vdarray* numericValues;
84     grib_vsarray* stringValues;
85     grib_viarray* elementsDescriptorsIndex;
86     char* cname;
87 } grib_accessor_bufr_data_element;
88 
89 extern grib_accessor_class* grib_accessor_class_gen;
90 
91 static grib_accessor_class _grib_accessor_class_bufr_data_element = {
92     &grib_accessor_class_gen,                      /* super                     */
93     "bufr_data_element",                      /* name                      */
94     sizeof(grib_accessor_bufr_data_element),  /* size                      */
95     0,                           /* inited */
96     &init_class,                 /* init_class */
97     &init,                       /* init                      */
98     0,                  /* post_init                      */
99     &destroy,                    /* free mem                       */
100     &dump,                       /* describes himself         */
101     0,                /* get length of section     */
102     0,              /* get length of string      */
103     &value_count,                /* get number of values      */
104     0,                 /* get number of bytes      */
105     0,                /* get offset to bytes           */
106     &get_native_type,            /* get native type               */
107     0,                /* get sub_section                */
108     &pack_missing,               /* grib_pack procedures long      */
109     &is_missing,                 /* grib_pack procedures long      */
110     &pack_long,                  /* grib_pack procedures long      */
111     &unpack_long,                /* grib_unpack procedures long    */
112     &pack_double,                /* grib_pack procedures double    */
113     &unpack_double,              /* grib_unpack procedures double  */
114     &pack_string,                /* grib_pack procedures string    */
115     &unpack_string,              /* grib_unpack procedures string  */
116     &pack_string_array,          /* grib_pack array procedures string    */
117     &unpack_string_array,        /* grib_unpack array procedures string  */
118     0,                 /* grib_pack procedures bytes     */
119     0,               /* grib_unpack procedures bytes   */
120     0,            /* pack_expression */
121     0,              /* notify_change   */
122     0,                /* update_size   */
123     0,             /* preferred_size   */
124     0,                     /* resize   */
125     0,      /* nearest_smaller_value */
126     0,                       /* next accessor    */
127     0,                    /* compare vs. another accessor   */
128     &unpack_double_element,      /* unpack only ith value          */
129     0,     /* unpack a subarray         */
130     0,                      /* clear          */
131     &make_clone,                 /* clone accessor          */
132 };
133 
134 
135 grib_accessor_class* grib_accessor_class_bufr_data_element = &_grib_accessor_class_bufr_data_element;
136 
137 
init_class(grib_accessor_class * c)138 static void init_class(grib_accessor_class* c)
139 {
140     c->next_offset    =    (*(c->super))->next_offset;
141     c->string_length    =    (*(c->super))->string_length;
142     c->byte_count    =    (*(c->super))->byte_count;
143     c->byte_offset    =    (*(c->super))->byte_offset;
144     c->sub_section    =    (*(c->super))->sub_section;
145     c->pack_bytes    =    (*(c->super))->pack_bytes;
146     c->unpack_bytes    =    (*(c->super))->unpack_bytes;
147     c->pack_expression    =    (*(c->super))->pack_expression;
148     c->notify_change    =    (*(c->super))->notify_change;
149     c->update_size    =    (*(c->super))->update_size;
150     c->preferred_size    =    (*(c->super))->preferred_size;
151     c->resize    =    (*(c->super))->resize;
152     c->nearest_smaller_value    =    (*(c->super))->nearest_smaller_value;
153     c->next    =    (*(c->super))->next;
154     c->compare    =    (*(c->super))->compare;
155     c->unpack_double_subarray    =    (*(c->super))->unpack_double_subarray;
156     c->clear    =    (*(c->super))->clear;
157 }
158 
159 /* END_CLASS_IMP */
160 
make_clone(grib_accessor * a,grib_section * s,int * err)161 static grib_accessor* make_clone(grib_accessor* a, grib_section* s, int* err)
162 {
163     grib_accessor* the_clone = NULL;
164     grib_accessor* attribute = NULL;
165     grib_accessor_bufr_data_element* elementAccessor;
166     grib_accessor_bufr_data_element* self;
167     char* copied_name = NULL;
168     int i;
169     grib_action creator = {0,};
170     creator.op         = "bufr_data_element";
171     creator.name_space = "";
172     creator.set        = 0;
173     creator.name       = "unknown";
174     if (strcmp(a->cclass->name, "bufr_data_element")) {
175         grib_context_log(a->context, GRIB_LOG_FATAL, "wrong accessor type: '%s' should be '%s'", a->cclass->name, "bufr_data_element");
176     }
177     *err = 0;
178 
179     the_clone                                 = grib_accessor_factory(s, &creator, 0, NULL);
180     copied_name                               = grib_context_strdup(a->context, a->name);
181     the_clone->name                           = copied_name;
182     elementAccessor                           = (grib_accessor_bufr_data_element*)the_clone;
183     self                                      = (grib_accessor_bufr_data_element*)a;
184     the_clone->flags                          = a->flags;
185     the_clone->parent                         = NULL;
186     the_clone->h                              = s->h;
187     elementAccessor->index                    = self->index;
188     elementAccessor->type                     = self->type;
189     elementAccessor->numberOfSubsets          = self->numberOfSubsets;
190     elementAccessor->subsetNumber             = self->subsetNumber;
191     elementAccessor->compressedData           = self->compressedData;
192     elementAccessor->descriptors              = self->descriptors;
193     elementAccessor->numericValues            = self->numericValues;
194     elementAccessor->stringValues             = self->stringValues;
195     elementAccessor->elementsDescriptorsIndex = self->elementsDescriptorsIndex;
196     elementAccessor->cname                    = copied_name; /* ECC-765 */
197 
198     i = 0;
199     while (a->attributes[i]) {
200         attribute = grib_accessor_clone(a->attributes[i], s, err);
201         /* attribute->parent=a->parent; */
202         grib_accessor_add_attribute(the_clone, attribute, 0);
203         i++;
204     }
205 
206     return the_clone;
207 }
208 
accessor_bufr_data_element_set_index(grib_accessor * a,long index)209 void accessor_bufr_data_element_set_index(grib_accessor* a, long index)
210 {
211     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
212     self->index                           = index;
213 }
214 
accessor_bufr_data_element_set_type(grib_accessor * a,int type)215 void accessor_bufr_data_element_set_type(grib_accessor* a, int type)
216 {
217     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
218     self->type                            = type;
219 }
220 
accessor_bufr_data_element_set_numberOfSubsets(grib_accessor * a,long numberOfSubsets)221 void accessor_bufr_data_element_set_numberOfSubsets(grib_accessor* a, long numberOfSubsets)
222 {
223     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
224     self->numberOfSubsets                 = numberOfSubsets;
225 }
226 
accessor_bufr_data_element_set_subsetNumber(grib_accessor * a,long subsetNumber)227 void accessor_bufr_data_element_set_subsetNumber(grib_accessor* a, long subsetNumber)
228 {
229     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
230     self->subsetNumber                    = subsetNumber;
231 }
232 
accessor_bufr_data_element_set_compressedData(grib_accessor * a,int compressedData)233 void accessor_bufr_data_element_set_compressedData(grib_accessor* a, int compressedData)
234 {
235     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
236     self->compressedData                  = compressedData;
237 }
238 
accessor_bufr_data_element_set_descriptors(grib_accessor * a,bufr_descriptors_array * descriptors)239 void accessor_bufr_data_element_set_descriptors(grib_accessor* a, bufr_descriptors_array* descriptors)
240 {
241     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
242     self->descriptors                     = descriptors;
243 }
244 
accessor_bufr_data_element_set_numericValues(grib_accessor * a,grib_vdarray * numericValues)245 void accessor_bufr_data_element_set_numericValues(grib_accessor* a, grib_vdarray* numericValues)
246 {
247     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
248     self->numericValues                   = numericValues;
249 }
250 
accessor_bufr_data_element_set_stringValues(grib_accessor * a,grib_vsarray * stringValues)251 void accessor_bufr_data_element_set_stringValues(grib_accessor* a, grib_vsarray* stringValues)
252 {
253     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
254     self->stringValues                    = stringValues;
255 }
256 
accessor_bufr_data_element_set_elementsDescriptorsIndex(grib_accessor * a,grib_viarray * elementsDescriptorsIndex)257 void accessor_bufr_data_element_set_elementsDescriptorsIndex(grib_accessor* a, grib_viarray* elementsDescriptorsIndex)
258 {
259     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
260     self->elementsDescriptorsIndex        = elementsDescriptorsIndex;
261 }
262 
init(grib_accessor * a,const long len,grib_arguments * params)263 static void init(grib_accessor* a, const long len, grib_arguments* params)
264 {
265     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
266     a->length                             = 0;
267     a->flags |= GRIB_ACCESSOR_FLAG_BUFR_DATA;
268     /* a->flags |= GRIB_ACCESSOR_FLAG_READ_ONLY; */
269     self->cname = NULL;
270 }
271 
dump(grib_accessor * a,grib_dumper * dumper)272 static void dump(grib_accessor* a, grib_dumper* dumper)
273 {
274     int type = get_native_type(a);
275 
276     switch (type) {
277         case GRIB_TYPE_LONG:
278             grib_dump_long(dumper, a, NULL);
279             break;
280         case GRIB_TYPE_DOUBLE:
281             grib_dump_values(dumper, a);
282             break;
283         case GRIB_TYPE_STRING:
284             grib_dump_string_array(dumper, a, NULL);
285             break;
286     }
287 }
288 
unpack_string_array(grib_accessor * a,char ** val,size_t * len)289 static int unpack_string_array(grib_accessor* a, char** val, size_t* len)
290 {
291     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
292 
293     int ret         = 0, i, idx;
294     long count      = 0;
295     grib_context* c = a->context;
296 
297     if (self->compressedData) {
298         DebugAssert(self->index < self->numericValues->n);
299         idx = ((int)self->numericValues->v[self->index]->v[0] / 1000 - 1) / self->numberOfSubsets;
300         DebugAssert(idx < self->stringValues->n);
301         count = grib_sarray_used_size(self->stringValues->v[idx]);
302         for (i = 0; i < count; i++) {
303             val[i] = grib_context_strdup(c, self->stringValues->v[idx]->v[i]);
304         }
305         *len = count;
306     }
307     else {
308         DebugAssert(self->subsetNumber < self->numericValues->n);
309         DebugAssert(self->index < self->numericValues->v[self->subsetNumber]->n);
310         idx    = (int)self->numericValues->v[self->subsetNumber]->v[self->index] / 1000 - 1;
311         val[0] = grib_context_strdup(c, self->stringValues->v[idx]->v[0]);
312         *len   = 1;
313     }
314 
315     return ret;
316 }
317 
pack_string_array(grib_accessor * a,const char ** v,size_t * len)318 static int pack_string_array(grib_accessor* a, const char** v, size_t* len)
319 {
320     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
321 
322     int ret         = 0, i, idx;
323     char* s         = NULL;
324     grib_context* c = a->context;
325 
326     if (self->compressedData) {
327         idx = ((int)self->numericValues->v[self->index]->v[0] / 1000 - 1) / self->numberOfSubsets;
328         if (*len != 1 && *len != self->numberOfSubsets) {
329             grib_context_log(c, GRIB_LOG_ERROR, "Number of values mismatch for '%s': %ld strings provided but expected %ld (=number of subsets)",
330                              self->descriptors->v[self->elementsDescriptorsIndex->v[0]->v[idx]]->shortName, *len, self->numberOfSubsets);
331             return GRIB_ARRAY_TOO_SMALL;
332         }
333         grib_sarray_delete(c, self->stringValues->v[idx]);
334         self->stringValues->v[idx] = grib_sarray_new(c, *len, 1);
335         for (i = 0; i < *len; i++) {
336             s = grib_context_strdup(c, v[i]);
337             grib_sarray_push(c, self->stringValues->v[idx], s);
338         }
339     }
340     else {
341         ret = GRIB_NOT_IMPLEMENTED;
342     }
343 
344     return ret;
345 }
346 
unpack_string(grib_accessor * a,char * val,size_t * len)347 static int unpack_string(grib_accessor* a, char* val, size_t* len)
348 {
349     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
350     char* str                             = NULL;
351     char* p                               = 0;
352     size_t slen                           = 0;
353     char sval[100]                        = {0,};
354     double dval = 0;
355     size_t dlen = 1;
356 
357     int ret         = 0, idx;
358     grib_context* c = a->context;
359 
360     if (self->type != BUFR_DESCRIPTOR_TYPE_STRING) {
361         unpack_double(a, &dval, &dlen);
362         sprintf(sval, "%g", dval);
363         slen = strlen(sval);
364         if (*len < slen)
365             return GRIB_ARRAY_TOO_SMALL;
366         strcpy(val, sval);
367         return GRIB_SUCCESS;
368     }
369 
370     if (self->compressedData) {
371         DebugAssert(self->index < self->numericValues->n);
372         idx = ((int)self->numericValues->v[self->index]->v[0] / 1000 - 1) / self->numberOfSubsets;
373         if (idx < 0)
374             return GRIB_INTERNAL_ERROR;
375         str = grib_context_strdup(c, self->stringValues->v[idx]->v[0]);
376     }
377     else {
378         DebugAssert(self->subsetNumber < self->numericValues->n);
379         idx = (int)self->numericValues->v[self->subsetNumber]->v[self->index] / 1000 - 1;
380         if (idx < 0)
381             return GRIB_INTERNAL_ERROR;
382         DebugAssert(idx < self->stringValues->n);
383         str = grib_context_strdup(c, self->stringValues->v[idx]->v[0]);
384     }
385 
386     if (str == 0 || strlen(str) == 0) {
387         grib_context_free(c, str);
388         *len = 0;
389         *val = 0;
390         return ret;
391     }
392 
393     p = str;
394     while (*p != 0)
395         p++;
396     p--;
397     while (p != str) {
398         if (*p != ' ')
399             break;
400         else
401             *p = 0;
402         p--;
403     }
404     slen = strlen(str);
405     if (slen > *len)
406         return GRIB_ARRAY_TOO_SMALL;
407 
408     strcpy(val, str);
409     grib_context_free(c, str);
410     *len = slen;
411 
412     return ret;
413 }
414 
pack_string(grib_accessor * a,const char * val,size_t * len)415 static int pack_string(grib_accessor* a, const char* val, size_t* len)
416 {
417     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
418 
419     int ret         = 0, idx;
420     char* s         = NULL;
421     grib_context* c = a->context;
422 
423     if (self->compressedData) {
424         idx = ((int)self->numericValues->v[self->index]->v[0] / 1000 - 1) / self->numberOfSubsets;
425     }
426     else {
427         idx = (int)self->numericValues->v[self->subsetNumber]->v[self->index] / 1000 - 1;
428     }
429     grib_sarray_delete(c, self->stringValues->v[idx]);
430     self->stringValues->v[idx] = grib_sarray_new(c, 1, 1);
431     s                          = grib_context_strdup(c, val);
432     grib_sarray_push(c, self->stringValues->v[idx], s);
433 
434     return ret;
435 }
436 
unpack_long(grib_accessor * a,long * val,size_t * len)437 static int unpack_long(grib_accessor* a, long* val, size_t* len)
438 {
439     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
440     int ret                               = 0, i;
441     long count                            = 0;
442 
443     value_count(a, &count);
444 
445     if (*len < count)
446         return GRIB_ARRAY_TOO_SMALL;
447 
448     if (self->compressedData) {
449         for (i = 0; i < count; i++) {
450             DebugAssert(self->index < self->numericValues->n);
451             DebugAssert(i < self->numericValues->v[self->index]->n);
452             val[i] = self->numericValues->v[self->index]->v[i] == GRIB_MISSING_DOUBLE ? GRIB_MISSING_LONG : (long)self->numericValues->v[self->index]->v[i];
453         }
454         *len = count;
455     }
456     else {
457         DebugAssert(self->subsetNumber < self->numericValues->n);
458         DebugAssert(self->index < self->numericValues->v[self->subsetNumber]->n);
459         val[0] = self->numericValues->v[self->subsetNumber]->v[self->index] == GRIB_MISSING_DOUBLE ? GRIB_MISSING_LONG : (long)self->numericValues->v[self->subsetNumber]->v[self->index];
460         *len   = 1;
461     }
462 
463     return ret;
464 }
465 
unpack_double(grib_accessor * a,double * val,size_t * len)466 static int unpack_double(grib_accessor* a, double* val, size_t* len)
467 {
468     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
469     int ret                               = 0, i;
470     long count                            = 0;
471 
472     value_count(a, &count);
473 
474     if (*len < count)
475         return GRIB_ARRAY_TOO_SMALL;
476 
477     if (self->compressedData) {
478         for (i = 0; i < count; i++) {
479             DebugAssert(self->index < self->numericValues->n);
480             DebugAssert(i < self->numericValues->v[self->index]->n);
481             val[i] = self->numericValues->v[self->index]->v[i];
482         }
483         *len = count;
484     }
485     else {
486         DebugAssert(self->subsetNumber < self->numericValues->n);
487         DebugAssert(self->index < self->numericValues->v[self->subsetNumber]->n);
488         val[0] = self->numericValues->v[self->subsetNumber]->v[self->index];
489         *len   = 1;
490     }
491 
492     return ret;
493 }
494 
pack_double(grib_accessor * a,const double * val,size_t * len)495 static int pack_double(grib_accessor* a, const double* val, size_t* len)
496 {
497     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
498     int ret                               = 0, i;
499     long count                            = 1;
500     grib_context* c                       = a->context;
501 
502     if (self->compressedData) {
503         count = *len;
504         if (count != 1 && count != self->numberOfSubsets) {
505             grib_context_log(c, GRIB_LOG_ERROR, "Number of values mismatch for '%s': %ld doubles provided but expected %ld (=number of subsets)",
506                              self->descriptors->v[self->elementsDescriptorsIndex->v[0]->v[self->index]]->shortName, count, self->numberOfSubsets);
507             return GRIB_ARRAY_TOO_SMALL;
508         }
509         grib_darray_delete(a->context, self->numericValues->v[self->index]);
510         self->numericValues->v[self->index] = grib_darray_new(a->context, count, 1);
511 
512         for (i = 0; i < count; i++)
513             grib_darray_push(a->context, self->numericValues->v[self->index], val[i]);
514 
515         *len = count;
516     }
517     else {
518         self->numericValues->v[self->subsetNumber]->v[self->index] = val[0];
519         *len                                                       = 1;
520     }
521 
522     return ret;
523 }
524 
pack_long(grib_accessor * a,const long * val,size_t * len)525 static int pack_long(grib_accessor* a, const long* val, size_t* len)
526 {
527     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
528     int ret                               = 0, i;
529     long count                            = 1;
530     grib_context* c                       = a->context;
531 
532     if (self->compressedData) {
533         count = *len;
534         if (count != 1 && count != self->numberOfSubsets) {
535             grib_context_log(c, GRIB_LOG_ERROR, "Number of values mismatch for '%s': %ld integers provided but expected %ld (=number of subsets)",
536                              self->descriptors->v[self->elementsDescriptorsIndex->v[0]->v[self->index]]->shortName, count, self->numberOfSubsets);
537             return GRIB_ARRAY_TOO_SMALL;
538         }
539         grib_darray_delete(a->context, self->numericValues->v[self->index]);
540         self->numericValues->v[self->index] = grib_darray_new(a->context, count, 1);
541 
542         for (i = 0; i < count; i++) {
543             grib_darray_push(a->context, self->numericValues->v[self->index], val[i] == GRIB_MISSING_LONG ? GRIB_MISSING_DOUBLE : val[i]);
544         }
545         *len = count;
546     }
547     else {
548         self->numericValues->v[self->subsetNumber]->v[self->index] = val[0] == GRIB_MISSING_LONG ? GRIB_MISSING_DOUBLE : val[0];
549         *len                                                       = 1;
550     }
551 
552     return ret;
553 }
554 
value_count(grib_accessor * a,long * count)555 static int value_count(grib_accessor* a, long* count)
556 {
557     int ret                               = 0, size, type, idx;
558     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
559 
560     if (!self->compressedData) {
561         *count = 1;
562         return 0;
563     }
564     type = get_native_type(a);
565 
566     if (type == GRIB_TYPE_STRING) {
567         DebugAssert(self->index < self->numericValues->n);
568         idx  = ((int)self->numericValues->v[self->index]->v[0] / 1000 - 1) / self->numberOfSubsets;
569         size = grib_sarray_used_size(self->stringValues->v[idx]);
570     }
571     else {
572         DebugAssert(self->index < self->numericValues->n);
573         size = grib_darray_used_size(self->numericValues->v[self->index]);
574     }
575 
576     *count = size == 1 ? 1 : self->numberOfSubsets;
577 
578     return ret;
579 }
580 
unpack_double_element(grib_accessor * a,size_t idx,double * val)581 static int unpack_double_element(grib_accessor* a, size_t idx, double* val)
582 {
583     /* ECC-415 */
584     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
585     int ret                               = GRIB_SUCCESS;
586     long count                            = 0;
587 
588     value_count(a, &count);
589     if (idx >= count) {
590         return GRIB_INTERNAL_ERROR;
591     }
592 
593     if (self->compressedData) {
594         *val = self->numericValues->v[self->index]->v[idx];
595     }
596     else {
597         ret = GRIB_NOT_IMPLEMENTED;
598     }
599     return ret;
600 }
601 
get_native_type(grib_accessor * a)602 static int get_native_type(grib_accessor* a)
603 {
604     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
605     int ret                               = GRIB_TYPE_DOUBLE;
606 
607     switch (self->type) {
608         case BUFR_DESCRIPTOR_TYPE_STRING:
609             ret = GRIB_TYPE_STRING;
610             break;
611         case BUFR_DESCRIPTOR_TYPE_DOUBLE:
612             ret = GRIB_TYPE_DOUBLE;
613             break;
614         case BUFR_DESCRIPTOR_TYPE_LONG:
615             ret = GRIB_TYPE_LONG;
616             break;
617         case BUFR_DESCRIPTOR_TYPE_TABLE:
618             ret = GRIB_TYPE_LONG;
619             break;
620         case BUFR_DESCRIPTOR_TYPE_FLAG:
621             ret = GRIB_TYPE_LONG;
622             break;
623     }
624 
625     return ret;
626 }
627 
destroy(grib_context * ct,grib_accessor * a)628 static void destroy(grib_context* ct, grib_accessor* a)
629 {
630     grib_accessor_bufr_data_element* self = (grib_accessor_bufr_data_element*)a;
631     int i                                 = 0;
632     if (self->cname)
633         grib_context_free(ct, self->cname); /* ECC-765 */
634     while (i < MAX_ACCESSOR_ATTRIBUTES && a->attributes[i]) {
635         /*grib_context_log(ct,GRIB_LOG_DEBUG,"deleting attribute %s->%s",a->name,a->attributes[i]->name);*/
636         /*printf("bufr_data_element destroy %s %p\n", a->attributes[i]->name, (void*)a->attributes[i]);*/
637         grib_accessor_delete(ct, a->attributes[i]);
638         a->attributes[i] = NULL;
639         i++;
640     }
641 }
642 
643 #define MAX_STRING_SIZE 4096
644 /* Return 1 if BUFR element(s) is/are missing, 0 otherwise. In case of decoding errors, also return 0 */
is_missing(grib_accessor * a)645 static int is_missing(grib_accessor* a)
646 {
647     const int ktype = get_native_type(a);
648     int err = 0, result = 1; /* default: assume all are missing */
649     long count = 0;
650     size_t i = 0, size = 1, size2 = 0;
651     grib_context* c = a->context;
652 
653     if (ktype == GRIB_TYPE_LONG) {
654         long* values           = NULL;
655         long value             = 0;
656 
657         value_count(a, &count);
658         size = size2 = count;
659         if (size > 1) {
660             values = (long*)grib_context_malloc_clear(c, sizeof(long) * size);
661             err    = grib_unpack_long(a, values, &size2);
662         }
663         else {
664             err = grib_unpack_long(a, &value, &size2);
665         }
666         if (err) return 0; /* TODO: no way of propagating the error up */
667         Assert(size2 == size);
668         if (size > 1) {
669             for (i = 0; i < size; i++) {
670                 if (!grib_is_missing_long(a, values[i])) {
671                     result = 0; /* at least one not missing */
672                     break;
673                 }
674             }
675             grib_context_free(c, values);
676         } else {
677             result = grib_is_missing_long(a, value);
678         }
679     }
680     else if (ktype == GRIB_TYPE_DOUBLE) {
681         double value           = 0;
682         double* values         = NULL;
683 
684         value_count(a, &count);
685         size = size2 = count;
686         if (size > 1) {
687             values = (double*)grib_context_malloc_clear(c, sizeof(double) * size);
688             err    = grib_unpack_double(a, values, &size2);
689         }
690         else {
691             err = grib_unpack_double(a, &value, &size2);
692         }
693         if (err) return 0; /* TODO: no way of propagating the error up */
694         Assert(size2 == size);
695         if (size > 1) {
696             for (i = 0; i < size; ++i) {
697                 if (!grib_is_missing_double(a, values[i])) {
698                     result = 0;
699                     break;
700                 }
701             }
702             grib_context_free(c, values);
703         }
704         else {
705             result = grib_is_missing_double(a, value);
706         }
707     }
708     else if (ktype == GRIB_TYPE_STRING) {
709         char** values          = NULL;
710         value_count(a, &count);
711         size = count;
712         if (size > 1) {
713             values = (char**)grib_context_malloc_clear(a->context, size * sizeof(char*));
714             err = grib_unpack_string_array(a, values, &size);
715             if (err) return 0; /* TODO: no way of propagating the error up */
716             for (i = 0; i < size; i++) {
717                 if (!grib_is_missing_string(a, (unsigned char*)values[i], size)) {
718                     result = 0;
719                     break;
720                 }
721             }
722             for (i = 0; i < size; i++) grib_context_free(c, values[i]);
723             grib_context_free(c, values);
724         } else {
725             char value[MAX_STRING_SIZE] = {0,}; /* See ECC-710 */
726             size = MAX_STRING_SIZE;
727             err = grib_unpack_string(a, value, &size);
728             if (err) return 0; /* TODO: no way of propagating the error up */
729             result = grib_is_missing_string(a, (unsigned char*)value, size);
730         }
731     }
732     else {
733         return GRIB_INVALID_TYPE;
734     }
735     return result;
736 }
737 
pack_missing(grib_accessor * a)738 static int pack_missing(grib_accessor* a)
739 {
740     int ktype = GRIB_TYPE_UNDEFINED;
741     int err = 0;
742     size_t size = 1;
743     const int can_be_missing = (a->flags & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING);
744     if (!can_be_missing)
745         return GRIB_VALUE_CANNOT_BE_MISSING;
746 
747     ktype = get_native_type(a);
748     if (ktype == GRIB_TYPE_LONG) {
749         long missing = GRIB_MISSING_LONG;
750         err = pack_long(a, &missing, &size);
751     }
752     else if (ktype == GRIB_TYPE_DOUBLE) {
753         double missing = GRIB_MISSING_DOUBLE;
754         err = pack_double(a, &missing, &size);
755     }
756     else if (ktype == GRIB_TYPE_STRING) {
757         err = pack_string(a, "", &size);
758     }
759     else {
760         err = GRIB_INVALID_TYPE;
761     }
762 
763     return err;
764 }
765