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