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 * Jean Baptiste Filippi - 01.11.2005 *
13 * Enrico Fucile
14 * *
15 ***************************************************************************/
16 #include "grib_api_internal.h"
17 /*
18 This is used by make_class.pl
19
20 START_CLASS_DEF
21 CLASS = accessor
22 IMPLEMENTS = unpack_long;pack_long; clear
23 IMPLEMENTS = unpack_double;pack_double;unpack_double_element
24 IMPLEMENTS = unpack_string;pack_string
25 IMPLEMENTS = unpack_string_array;pack_string_array
26 IMPLEMENTS = unpack_bytes;pack_bytes
27 IMPLEMENTS = unpack_double_subarray
28 IMPLEMENTS = init;dump;destroy;string_length
29 IMPLEMENTS = get_native_type;sub_section
30 IMPLEMENTS = next_offset;value_count;byte_offset;byte_count
31 IMPLEMENTS = notify_change;pack_expression
32 IMPLEMENTS = update_size; next; preferred_size
33 IMPLEMENTS = compare;is_missing;make_clone
34 END_CLASS_DEF
35
36 */
37
38 /* START_CLASS_IMP */
39
40 /*
41
42 Don't edit anything between START_CLASS_IMP and END_CLASS_IMP
43 Instead edit values between START_CLASS_DEF and END_CLASS_DEF
44 or edit "accessor.class" and rerun ./make_class.pl
45
46 */
47
48 static grib_section* sub_section(grib_accessor* a);
49 static int get_native_type(grib_accessor*);
50 static int is_missing(grib_accessor*);
51 static int pack_bytes(grib_accessor*, const unsigned char*, size_t* len);
52 static int pack_double(grib_accessor*, const double* val, size_t* len);
53 static int pack_long(grib_accessor*, const long* val, size_t* len);
54 static int pack_string(grib_accessor*, const char*, size_t* len);
55 static int pack_string_array(grib_accessor*, const char**, size_t* len);
56 static int pack_expression(grib_accessor*, grib_expression*);
57 static int unpack_bytes(grib_accessor*, unsigned char*, size_t* len);
58 static int unpack_double(grib_accessor*, double* val, size_t* len);
59 static int unpack_long(grib_accessor*, long* val, size_t* len);
60 static int unpack_string(grib_accessor*, char*, size_t* len);
61 static int unpack_string_array(grib_accessor*, char**, size_t* len);
62 static size_t string_length(grib_accessor*);
63 static long byte_count(grib_accessor*);
64 static long byte_offset(grib_accessor*);
65 static long next_offset(grib_accessor*);
66 static int value_count(grib_accessor*, long*);
67 static void destroy(grib_context*, grib_accessor*);
68 static void dump(grib_accessor*, grib_dumper*);
69 static void init(grib_accessor*, const long, grib_arguments*);
70 static void init_class(grib_accessor_class*);
71 static int notify_change(grib_accessor*, grib_accessor*);
72 static void update_size(grib_accessor*, size_t);
73 static size_t preferred_size(grib_accessor*, int);
74 static grib_accessor* next(grib_accessor*, int);
75 static int compare(grib_accessor*, grib_accessor*);
76 static int unpack_double_element(grib_accessor*, size_t i, double* val);
77 static int unpack_double_subarray(grib_accessor*, double* val, size_t start, size_t len);
78 static int clear(grib_accessor*);
79 static grib_accessor* make_clone(grib_accessor*, grib_section*, int*);
80
81 typedef struct grib_accessor_gen
82 {
83 grib_accessor att;
84 /* Members defined in gen */
85 } grib_accessor_gen;
86
87
88 static grib_accessor_class _grib_accessor_class_gen = {
89 0, /* super */
90 "gen", /* name */
91 sizeof(grib_accessor_gen), /* size */
92 0, /* inited */
93 &init_class, /* init_class */
94 &init, /* init */
95 0, /* post_init */
96 &destroy, /* free mem */
97 &dump, /* describes himself */
98 &next_offset, /* get length of section */
99 &string_length, /* get length of string */
100 &value_count, /* get number of values */
101 &byte_count, /* get number of bytes */
102 &byte_offset, /* get offset to bytes */
103 &get_native_type, /* get native type */
104 &sub_section, /* get sub_section */
105 0, /* grib_pack procedures long */
106 &is_missing, /* grib_pack procedures long */
107 &pack_long, /* grib_pack procedures long */
108 &unpack_long, /* grib_unpack procedures long */
109 &pack_double, /* grib_pack procedures double */
110 &unpack_double, /* grib_unpack procedures double */
111 &pack_string, /* grib_pack procedures string */
112 &unpack_string, /* grib_unpack procedures string */
113 &pack_string_array, /* grib_pack array procedures string */
114 &unpack_string_array, /* grib_unpack array procedures string */
115 &pack_bytes, /* grib_pack procedures bytes */
116 &unpack_bytes, /* grib_unpack procedures bytes */
117 &pack_expression, /* pack_expression */
118 ¬ify_change, /* notify_change */
119 &update_size, /* update_size */
120 &preferred_size, /* preferred_size */
121 0, /* resize */
122 0, /* nearest_smaller_value */
123 &next, /* next accessor */
124 &compare, /* compare vs. another accessor */
125 &unpack_double_element, /* unpack only ith value */
126 &unpack_double_subarray, /* unpack a subarray */
127 &clear, /* clear */
128 &make_clone, /* clone accessor */
129 };
130
131
132 grib_accessor_class* grib_accessor_class_gen = &_grib_accessor_class_gen;
133
134
init_class(grib_accessor_class * c)135 static void init_class(grib_accessor_class* c)
136 {
137 }
138
139 /* END_CLASS_IMP */
140
init(grib_accessor * a,const long len,grib_arguments * param)141 static void init(grib_accessor* a, const long len, grib_arguments* param)
142 {
143 grib_action* act = (grib_action*)(a->creator);
144 if (a->flags & GRIB_ACCESSOR_FLAG_TRANSIENT) {
145 a->length = 0;
146 if (!a->vvalue)
147 a->vvalue = (grib_virtual_value*)grib_context_malloc_clear(a->context, sizeof(grib_virtual_value));
148 a->vvalue->type = grib_accessor_get_native_type(a);
149 a->vvalue->length = len;
150 if (act->default_value != NULL) {
151 const char* p = 0;
152 size_t s_len = 1;
153 long l;
154 int ret = 0;
155 double d;
156 char tmp[1024];
157 grib_expression* expression = grib_arguments_get_expression(grib_handle_of_accessor(a), act->default_value, 0);
158 int type = grib_expression_native_type(grib_handle_of_accessor(a), expression);
159 switch (type) {
160 case GRIB_TYPE_DOUBLE:
161 grib_expression_evaluate_double(grib_handle_of_accessor(a), expression, &d);
162 grib_pack_double(a, &d, &s_len);
163 break;
164
165 case GRIB_TYPE_LONG:
166 grib_expression_evaluate_long(grib_handle_of_accessor(a), expression, &l);
167 grib_pack_long(a, &l, &s_len);
168 break;
169
170 default:
171 s_len = sizeof(tmp);
172 p = grib_expression_evaluate_string(grib_handle_of_accessor(a), expression, tmp, &s_len, &ret);
173 if (ret != GRIB_SUCCESS) {
174 grib_context_log(a->context, GRIB_LOG_ERROR, "Unable to evaluate %s as string", a->name);
175 Assert(0);
176 }
177 s_len = strlen(p) + 1;
178 grib_pack_string(a, p, &s_len);
179 break;
180 }
181 }
182 }
183 else {
184 a->length = len;
185 }
186 }
187
dump(grib_accessor * a,grib_dumper * dumper)188 static void dump(grib_accessor* a, grib_dumper* dumper)
189 {
190 int type = grib_accessor_get_native_type(a);
191
192 switch (type) {
193 case GRIB_TYPE_STRING:
194 grib_dump_string(dumper, a, NULL);
195 break;
196 case GRIB_TYPE_DOUBLE:
197 grib_dump_double(dumper, a, NULL);
198 break;
199 case GRIB_TYPE_LONG:
200 grib_dump_long(dumper, a, NULL);
201 break;
202 default:
203 grib_dump_bytes(dumper, a, NULL);
204 }
205 }
206
next_offset(grib_accessor * a)207 static long next_offset(grib_accessor* a)
208 {
209 return a->offset + a->length;
210 }
211
value_count(grib_accessor * a,long * count)212 static int value_count(grib_accessor* a, long* count)
213 {
214 *count = 1;
215 return 0;
216 }
217
string_length(grib_accessor * a)218 static size_t string_length(grib_accessor* a)
219 {
220 return 1024;
221 }
222
byte_count(grib_accessor * a)223 static long byte_count(grib_accessor* a)
224 {
225 return a->length;
226 }
227
get_native_type(grib_accessor * a)228 static int get_native_type(grib_accessor* a)
229 {
230 grib_context_log(a->context, GRIB_LOG_ERROR,
231 "Accessor %s [%s] must implement 'get_native_type'", a->name, a->cclass->name);
232 return GRIB_TYPE_UNDEFINED;
233 }
234
byte_offset(grib_accessor * a)235 static long byte_offset(grib_accessor* a)
236 {
237 return a->offset;
238 }
239
unpack_bytes(grib_accessor * a,unsigned char * val,size_t * len)240 static int unpack_bytes(grib_accessor* a, unsigned char* val, size_t* len)
241 {
242 unsigned char* buf = grib_handle_of_accessor(a)->buffer->data;
243 long length = grib_byte_count(a);
244 long offset = grib_byte_offset(a);
245
246 if (*len < length) {
247 grib_context_log(a->context, GRIB_LOG_ERROR, "Wrong size for %s it is %d bytes long\n", a->name, length);
248 *len = length;
249 return GRIB_ARRAY_TOO_SMALL;
250 }
251
252 memcpy(val, buf + offset, length);
253 *len = length;
254
255 return GRIB_SUCCESS;
256 }
257
clear(grib_accessor * a)258 static int clear(grib_accessor* a)
259 {
260 unsigned char* buf = grib_handle_of_accessor(a)->buffer->data;
261 long length = grib_byte_count(a);
262 long offset = grib_byte_offset(a);
263
264 memset(buf + offset, 0, length);
265
266 return GRIB_SUCCESS;
267 }
268
unpack_long(grib_accessor * a,long * v,size_t * len)269 static int unpack_long(grib_accessor* a, long* v, size_t* len)
270 {
271 int type = GRIB_TYPE_UNDEFINED;
272 if (a->cclass->unpack_double && a->cclass->unpack_double != &unpack_double) {
273 double val = 0.0;
274 size_t l = 1;
275 grib_unpack_double(a, &val, &l);
276 if (val == GRIB_MISSING_DOUBLE)
277 *v = GRIB_MISSING_LONG;
278 else
279 *v = (long)val;
280 grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting double %s to long", a->name);
281 return GRIB_SUCCESS;
282 }
283
284 if (a->cclass->unpack_string && a->cclass->unpack_string != &unpack_string) {
285 char val[1024];
286 size_t l = sizeof(val);
287 char* last = NULL;
288 grib_unpack_string(a, val, &l);
289
290 *v = strtol(val, &last, 10);
291
292 if (*last == 0) {
293 grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting string %s to long", a->name);
294 return GRIB_SUCCESS;
295 }
296 }
297
298 grib_context_log(a->context, GRIB_LOG_ERROR, "Cannot unpack %s as long", a->name);
299 if (grib_get_native_type(grib_handle_of_accessor(a), a->name, &type) == GRIB_SUCCESS) {
300 grib_context_log(a->context, GRIB_LOG_ERROR, "Hint: Try unpacking as %s", grib_get_type_name(type));
301 }
302 return GRIB_NOT_IMPLEMENTED;
303 }
304
unpack_double(grib_accessor * a,double * v,size_t * len)305 static int unpack_double(grib_accessor* a, double* v, size_t* len)
306 {
307 int type = GRIB_TYPE_UNDEFINED;
308 if (a->cclass->unpack_long && a->cclass->unpack_long != &unpack_long) {
309 long val = 0;
310 size_t l = 1;
311 grib_unpack_long(a, &val, &l);
312 *v = val;
313 grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting long %s to double", a->name);
314 return GRIB_SUCCESS;
315 }
316
317 if (a->cclass->unpack_string && a->cclass->unpack_string != &unpack_string) {
318 char val[1024];
319 size_t l = sizeof(val);
320 char* last = NULL;
321 grib_unpack_string(a, val, &l);
322
323 *v = strtod(val, &last);
324
325 if (*last == 0) {
326 grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting string %s to long", a->name);
327 return GRIB_SUCCESS;
328 }
329 }
330
331 grib_context_log(a->context, GRIB_LOG_ERROR, "Cannot unpack %s as double", a->name);
332 if (grib_get_native_type(grib_handle_of_accessor(a), a->name, &type) == GRIB_SUCCESS) {
333 grib_context_log(a->context, GRIB_LOG_ERROR, "Hint: Try unpacking as %s", grib_get_type_name(type));
334 }
335
336 return GRIB_NOT_IMPLEMENTED;
337 }
338
unpack_string(grib_accessor * a,char * v,size_t * len)339 static int unpack_string(grib_accessor* a, char* v, size_t* len)
340 {
341 if (a->cclass->unpack_double && a->cclass->unpack_double != &unpack_double) {
342 double val = 0.0;
343 size_t l = 1;
344 grib_unpack_double(a, &val, &l);
345 sprintf(v, "%g", val);
346 *len = strlen(v);
347 grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting double %s to string", a->name);
348 return GRIB_SUCCESS;
349 }
350
351 if (a->cclass->unpack_long && a->cclass->unpack_long != &unpack_long) {
352 long val = 0;
353 size_t l = 1;
354 grib_unpack_long(a, &val, &l);
355 sprintf(v, "%ld", val);
356 *len = strlen(v);
357 grib_context_log(a->context, GRIB_LOG_DEBUG, "Casting long %s to string \n", a->name);
358 return GRIB_SUCCESS;
359 }
360
361 return GRIB_NOT_IMPLEMENTED;
362 }
363
unpack_string_array(grib_accessor * a,char ** v,size_t * len)364 static int unpack_string_array(grib_accessor* a, char** v, size_t* len)
365 {
366 int err = 0;
367 size_t length = 0;
368
369 err = _grib_get_string_length(a, &length);
370 if (err)
371 return err;
372 v[0] = (char*)grib_context_malloc_clear(a->context, length);
373 grib_unpack_string(a, v[0], &length);
374 *len = 1;
375
376 return GRIB_SUCCESS;
377 }
378
pack_expression(grib_accessor * a,grib_expression * e)379 static int pack_expression(grib_accessor* a, grib_expression* e)
380 {
381 size_t len = 1;
382 long lval = 0;
383 double dval = 0;
384 const char* cval = NULL;
385 int ret = 0;
386 grib_handle* hand = grib_handle_of_accessor(a);
387
388 switch (grib_accessor_get_native_type(a)) {
389 case GRIB_TYPE_LONG: {
390 len = 1;
391 ret = grib_expression_evaluate_long(hand, e, &lval);
392 if (ret != GRIB_SUCCESS) {
393 grib_context_log(a->context, GRIB_LOG_ERROR, "Unable to set %s as long (from %s)",
394 a->name, e->cclass->name);
395 return ret;
396 }
397 /*if (hand->context->debug)
398 printf("ECCODES DEBUG grib_accessor_class_gen::pack_expression %s %ld\n", a->name,lval);*/
399 return grib_pack_long(a, &lval, &len);
400 }
401
402 case GRIB_TYPE_DOUBLE: {
403 len = 1;
404 ret = grib_expression_evaluate_double(hand, e, &dval);
405 if (ret != GRIB_SUCCESS) {
406 grib_context_log(a->context, GRIB_LOG_ERROR, "unable to set %s as double (from %s)",
407 a->name, e->cclass->name);
408 return ret;
409 }
410 /*if (hand->context->debug)
411 printf("ECCODES DEBUG grib_accessor_class_gen::pack_expression %s %g\n", a->name, dval);*/
412 return grib_pack_double(a, &dval, &len);
413 }
414
415 case GRIB_TYPE_STRING: {
416 char tmp[1024];
417 len = sizeof(tmp);
418 cval = grib_expression_evaluate_string(hand, e, tmp, &len, &ret);
419 if (ret != GRIB_SUCCESS) {
420 grib_context_log(a->context, GRIB_LOG_ERROR, "unable to set %s as string (from %s)",
421 a->name, e->cclass->name);
422 return ret;
423 }
424 len = strlen(cval);
425 /*if (hand->context->debug)
426 printf("ECCODES DEBUG grib_accessor_class_gen::pack_expression %s %s\n", a->name, cval);*/
427 return grib_pack_string(a, cval, &len);
428 }
429 }
430
431 return GRIB_NOT_IMPLEMENTED;
432 }
433
pack_long(grib_accessor * a,const long * v,size_t * len)434 static int pack_long(grib_accessor* a, const long* v, size_t* len)
435 {
436 grib_context* c = a->context;
437 if (a->cclass->pack_double && a->cclass->pack_double != &pack_double) {
438 int i = 0, ret = 0;
439 double* val = (double*)grib_context_malloc(c, *len * (sizeof(double)));
440 if (!val) {
441 grib_context_log(c, GRIB_LOG_ERROR,
442 "Unable to allocate %d bytes\n", (int)(*len * (sizeof(double))));
443 return GRIB_OUT_OF_MEMORY;
444 }
445 for (i = 0; i < *len; i++)
446 val[i] = (long)v[i];
447 ret = grib_pack_double(a, val, len);
448 grib_context_free(c, val);
449 return ret;
450 }
451 grib_context_log(c, GRIB_LOG_ERROR, "Should not grib_pack %s as long", a->name);
452 Assert(0);
453 return GRIB_NOT_IMPLEMENTED;
454 }
455
pack_double_array_as_long(grib_accessor * a,const double * v,size_t * len)456 static int pack_double_array_as_long(grib_accessor* a, const double* v, size_t* len)
457 {
458 grib_context* c = a->context;
459 int ret = GRIB_SUCCESS;
460 size_t i = 0;
461 size_t numBytes = *len * (sizeof(long));
462 long* lValues = (long*)grib_context_malloc(c, numBytes);
463 if (!lValues) {
464 grib_context_log(c, GRIB_LOG_ERROR, "Unable to allocate %ld bytes\n", numBytes);
465 return GRIB_OUT_OF_MEMORY;
466 }
467 for (i = 0; i < *len; i++)
468 lValues[i] = (long)v[i]; /* convert from double to long */
469 ret = grib_pack_long(a, lValues, len);
470 grib_context_free(c, lValues);
471 return ret;
472 }
473
pack_double(grib_accessor * a,const double * v,size_t * len)474 static int pack_double(grib_accessor* a, const double* v, size_t* len)
475 {
476 int do_pack_as_long = 0;
477 grib_context* c = a->context;
478 if (a->cclass->pack_long && a->cclass->pack_long != &pack_long) {
479 do_pack_as_long = 1;
480 }
481 else {
482 /* ECC-648: Special case of codetable */
483 if (strcmp(a->cclass->name, "codetable") == 0) {
484 do_pack_as_long = 1;
485 }
486 }
487 if (do_pack_as_long) {
488 return pack_double_array_as_long(a, v, len);
489 }
490 grib_context_log(c, GRIB_LOG_ERROR, "Should not grib_pack %s as double", a->name);
491 return GRIB_NOT_IMPLEMENTED;
492 }
493
pack_string_array(grib_accessor * a,const char ** v,size_t * len)494 static int pack_string_array(grib_accessor* a, const char** v, size_t* len)
495 {
496 long i;
497 int err = 0;
498 size_t length = 0;
499 grib_accessor* as = 0;
500
501 as = a;
502 i = (long)*len - 1;
503 while (as && i >= 0) {
504 length = strlen(v[i]);
505 err = grib_pack_string(as, v[i], &length);
506 if (err)
507 return err;
508 --i;
509 as = as->same;
510 }
511 return GRIB_SUCCESS;
512 }
513
pack_string(grib_accessor * a,const char * v,size_t * len)514 static int pack_string(grib_accessor* a, const char* v, size_t* len)
515 {
516 if (a->cclass->pack_double && a->cclass->pack_double != &pack_double) {
517 size_t l = 1;
518 double val = atof(v);
519 return grib_pack_double(a, &val, &l);
520 }
521
522 if (a->cclass->pack_long && a->cclass->pack_long != &pack_long) {
523 size_t l = 1;
524 long val = atof(v);
525 return grib_pack_long(a, &val, &l);
526 }
527
528 grib_context_log(a->context, GRIB_LOG_ERROR,
529 "Should not grib_pack %s as string", a->name);
530 return GRIB_NOT_IMPLEMENTED;
531 }
532
pack_bytes(grib_accessor * a,const unsigned char * val,size_t * len)533 static int pack_bytes(grib_accessor* a, const unsigned char* val, size_t* len)
534 {
535 const size_t length = *len;
536 if (length != a->length) {
537 grib_context_log(a->context, GRIB_LOG_ERROR,
538 "pack_bytes: Wrong size (%lu) for %s. It is %lu bytes long",
539 length, a->name, a->length);
540 return GRIB_BUFFER_TOO_SMALL;
541 }
542 grib_buffer_replace(a, val, length, 1, 1);
543 return GRIB_SUCCESS;
544 }
545
destroy(grib_context * ct,grib_accessor * a)546 static void destroy(grib_context* ct, grib_accessor* a)
547 {
548 grib_dependency_remove_observed(a);
549 grib_dependency_remove_observer(a);
550 if (a->vvalue != NULL) {
551 grib_context_free(ct, a->vvalue);
552 a->vvalue = NULL;
553 }
554 /*grib_context_log(ct,GRIB_LOG_DEBUG,"address=%p",a);*/
555 }
556
sub_section(grib_accessor * a)557 static grib_section* sub_section(grib_accessor* a)
558 {
559 return NULL;
560 }
561
notify_change(grib_accessor * self,grib_accessor * observed)562 static int notify_change(grib_accessor* self, grib_accessor* observed)
563 {
564 /* Default behaviour is to notify creator */
565 return grib_action_notify_change(self->creator, self, observed);
566 }
567
update_size(grib_accessor * a,size_t s)568 static void update_size(grib_accessor* a, size_t s)
569 {
570 grib_context_log(a->context, GRIB_LOG_ERROR,
571 "Accessor %s [%s] must implement 'update_size'", a->name, a->cclass->name);
572 Assert(0 == 1);
573 }
574
next(grib_accessor * a,int mod)575 static grib_accessor* next(grib_accessor* a, int mod)
576 {
577 grib_accessor* next = NULL;
578 if (a->next) {
579 next = a->next;
580 }
581 else {
582 if (a->parent->owner)
583 next = a->parent->owner->cclass->next(a->parent->owner, 0);
584 }
585 return next;
586 }
587
compare(grib_accessor * a,grib_accessor * b)588 static int compare(grib_accessor* a, grib_accessor* b)
589 {
590 return GRIB_NOT_IMPLEMENTED;
591 }
592
593 /* Redefined in all padding */
594
preferred_size(grib_accessor * a,int from_handle)595 static size_t preferred_size(grib_accessor* a, int from_handle)
596 {
597 return a->length;
598 }
599
is_missing(grib_accessor * a)600 static int is_missing(grib_accessor* a)
601 {
602 int i = 0;
603 int is_missing = 1;
604 unsigned char ones = 0xff;
605 unsigned char* v = NULL;
606
607 if (a->flags & GRIB_ACCESSOR_FLAG_TRANSIENT) {
608 if (a->vvalue == NULL) {
609 grib_context_log(a->context, GRIB_LOG_ERROR, "%s internal error (flags=0x%X)", a->name, a->flags);
610 Assert(!"grib_accessor_class_gen::is_missing(): a->vvalue == NULL");
611 return 0;
612 }
613 return a->vvalue->missing;
614 }
615 Assert(a->length >= 0);
616
617 v = grib_handle_of_accessor(a)->buffer->data + a->offset;
618
619 for (i = 0; i < a->length; i++) {
620 if (*v != ones) {
621 is_missing = 0;
622 break;
623 }
624 v++;
625 }
626
627 return is_missing;
628 }
629
unpack_double_element(grib_accessor * a,size_t i,double * val)630 static int unpack_double_element(grib_accessor* a, size_t i, double* val)
631 {
632 return GRIB_NOT_IMPLEMENTED;
633 }
634
unpack_double_subarray(grib_accessor * a,double * val,size_t start,size_t len)635 static int unpack_double_subarray(grib_accessor* a, double* val, size_t start, size_t len)
636 {
637 return GRIB_NOT_IMPLEMENTED;
638 }
639
make_clone(grib_accessor * a,grib_section * s,int * err)640 static grib_accessor* make_clone(grib_accessor* a, grib_section* s, int* err)
641 {
642 *err = GRIB_NOT_IMPLEMENTED;
643 return NULL;
644 }
645