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 
17 #include "grib_api_internal.h"
18 
19 /* Note: A fast cut-down version of strcmp which does NOT return -1 */
20 /* 0 means input strings are equal and 1 means not equal */
grib_inline_strcmp(const char * a,const char * b)21 GRIB_INLINE static int grib_inline_strcmp(const char* a, const char* b)
22 {
23     if (*a != *b)
24         return 1;
25     while ((*a != 0 && *b != 0) && *(a) == *(b)) {
26         a++;
27         b++;
28     }
29     return (*a == 0 && *b == 0) ? 0 : 1;
30 }
31 
grib_accessor_dump(grib_accessor * a,grib_dumper * f)32 void grib_accessor_dump(grib_accessor* a, grib_dumper* f)
33 {
34     grib_accessor_class* c = a->cclass;
35     while (c) {
36         if (c->dump) {
37             c->dump(a, f);
38             return;
39         }
40         c = c->super ? *(c->super) : NULL;
41     }
42     DebugAssert(0);
43 }
44 
grib_pack_missing(grib_accessor * a)45 int grib_pack_missing(grib_accessor* a)
46 {
47     grib_accessor_class* c = a->cclass;
48     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (double) %g",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?(*v):0); */
49     while (c) {
50         if (c->pack_missing) {
51             return c->pack_missing(a);
52         }
53         c = c->super ? *(c->super) : NULL;
54     }
55     DebugAssert(0);
56     return 0;
57 }
58 
grib_pack_zero(grib_accessor * a)59 int grib_pack_zero(grib_accessor* a)
60 {
61     grib_accessor_class* c = a->cclass;
62     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (double) %g",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?(*v):0); */
63     while (c) {
64         if (c->clear) {
65             return c->clear(a);
66         }
67         c = c->super ? *(c->super) : NULL;
68     }
69     DebugAssert(0);
70     return 0;
71 }
72 
grib_is_missing_internal(grib_accessor * a)73 int grib_is_missing_internal(grib_accessor* a)
74 {
75     grib_accessor_class* c = a->cclass;
76     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (double) %g",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?(*v):0); */
77     while (c) {
78         if (c->is_missing) {
79             return c->is_missing(a);
80         }
81         c = c->super ? *(c->super) : NULL;
82     }
83     DebugAssert(0);
84     return 0;
85 }
86 
grib_pack_double(grib_accessor * a,const double * v,size_t * len)87 int grib_pack_double(grib_accessor* a, const double* v, size_t* len)
88 {
89     grib_accessor_class* c = a->cclass;
90     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (double) %g",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?(*v):0); */
91     while (c) {
92         if (c->pack_double) {
93             return c->pack_double(a, v, len);
94         }
95         c = c->super ? *(c->super) : NULL;
96     }
97     DebugAssert(0);
98     return 0;
99 }
100 
grib_pack_expression(grib_accessor * a,grib_expression * e)101 int grib_pack_expression(grib_accessor* a, grib_expression* e)
102 {
103     grib_accessor_class* c = a->cclass;
104     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (double) %g",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?(*v):0); */
105     while (c) {
106         if (c->pack_expression) {
107             return c->pack_expression(a, e);
108         }
109         c = c->super ? *(c->super) : NULL;
110     }
111     DebugAssert(0);
112     return 0;
113 }
114 
grib_pack_string(grib_accessor * a,const char * v,size_t * len)115 int grib_pack_string(grib_accessor* a, const char* v, size_t* len)
116 {
117     grib_accessor_class* c = a->cclass;
118     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (string) %s",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?v:"(null)");*/
119     while (c) {
120         if (c->pack_string) {
121             return c->pack_string(a, v, len);
122         }
123         c = c->super ? *(c->super) : NULL;
124     }
125     DebugAssert(0);
126     return 0;
127 }
128 
grib_pack_string_array(grib_accessor * a,const char ** v,size_t * len)129 int grib_pack_string_array(grib_accessor* a, const char** v, size_t* len)
130 {
131     grib_accessor_class* c = a->cclass;
132     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (string) %s",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?v:"(null)");*/
133     while (c) {
134         if (c->pack_string_array) {
135             return c->pack_string_array(a, v, len);
136         }
137         c = c->super ? *(c->super) : NULL;
138     }
139     DebugAssert(0);
140     return 0;
141 }
142 
grib_pack_long(grib_accessor * a,const long * v,size_t * len)143 int grib_pack_long(grib_accessor* a, const long* v, size_t* len)
144 {
145     grib_accessor_class* c = a->cclass;
146     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (long) %d",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?(*v):0); */
147     while (c) {
148         if (c->pack_long) {
149             return c->pack_long(a, v, len);
150         }
151         c = c->super ? *(c->super) : NULL;
152     }
153     DebugAssert(0);
154     return 0;
155 }
156 
grib_pack_bytes(grib_accessor * a,const unsigned char * v,size_t * len)157 int grib_pack_bytes(grib_accessor* a, const unsigned char* v, size_t* len)
158 {
159     grib_accessor_class* c = a->cclass;
160     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (bytes) %d",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?(*v):0); */
161     while (c) {
162         if (c->pack_bytes) {
163             return c->pack_bytes(a, v, len);
164         }
165         c = c->super ? *(c->super) : NULL;
166     }
167     DebugAssert(0);
168     return 0;
169 }
170 
grib_unpack_bytes(grib_accessor * a,unsigned char * v,size_t * len)171 int grib_unpack_bytes(grib_accessor* a, unsigned char* v, size_t* len)
172 {
173     grib_accessor_class* c = a->cclass;
174     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is unpacking (bytes)",(a->parent->owner)?(a->parent->owner->name):"root", a->name ); */
175     while (c) {
176         if (c->unpack_bytes) {
177             return c->unpack_bytes(a, v, len);
178         }
179         c = c->super ? *(c->super) : NULL;
180     }
181     DebugAssert(0);
182     return 0;
183 }
184 
grib_unpack_double_subarray(grib_accessor * a,double * v,size_t start,size_t len)185 int grib_unpack_double_subarray(grib_accessor* a, double* v, size_t start, size_t len)
186 {
187     grib_accessor_class* c = a->cclass;
188     while (c) {
189         if (c->unpack_double_subarray) {
190             return c->unpack_double_subarray(a, v, start, len);
191         }
192         c = c->super ? *(c->super) : NULL;
193     }
194     DebugAssert(0);
195     return 0;
196 }
197 
grib_unpack_double(grib_accessor * a,double * v,size_t * len)198 int grib_unpack_double(grib_accessor* a, double* v, size_t* len)
199 {
200     grib_accessor_class* c = a->cclass;
201     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is unpacking (double)",(a->parent->owner)?(a->parent->owner->name):"root", a->name ); */
202     while (c) {
203         if (c->unpack_double) {
204             return c->unpack_double(a, v, len);
205         }
206         c = c->super ? *(c->super) : NULL;
207     }
208     DebugAssert(0);
209     return 0;
210 }
211 
grib_unpack_double_element(grib_accessor * a,size_t i,double * v)212 int grib_unpack_double_element(grib_accessor* a, size_t i, double* v)
213 {
214     grib_accessor_class* c = a->cclass;
215     while (c) {
216         if (c->unpack_double_element) {
217             return c->unpack_double_element(a, i, v);
218         }
219         c = c->super ? *(c->super) : NULL;
220     }
221     return GRIB_NOT_IMPLEMENTED;
222 }
223 
grib_unpack_string(grib_accessor * a,char * v,size_t * len)224 int grib_unpack_string(grib_accessor* a, char* v, size_t* len)
225 {
226     grib_accessor_class* c = a->cclass;
227     /* grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is unpacking (string)",(a->parent->owner)?(a->parent->owner->name):"root", a->name ); */
228     while (c) {
229         if (c->unpack_string) {
230             return c->unpack_string(a, v, len);
231         }
232         c = c->super ? *(c->super) : NULL;
233     }
234     DebugAssert(0);
235     return 0;
236 }
237 
grib_unpack_string_array(grib_accessor * a,char ** v,size_t * len)238 int grib_unpack_string_array(grib_accessor* a, char** v, size_t* len)
239 {
240     grib_accessor_class* c = a->cclass;
241     while (c) {
242         if (c->unpack_string_array) {
243             return c->unpack_string_array(a, v, len);
244         }
245         c = c->super ? *(c->super) : NULL;
246     }
247     DebugAssert(0);
248     return 0;
249 }
250 
grib_accessors_list_unpack_long(grib_accessors_list * al,long * val,size_t * buffer_len)251 int grib_accessors_list_unpack_long(grib_accessors_list* al, long* val, size_t* buffer_len)
252 {
253     int err             = GRIB_SUCCESS;
254     size_t unpacked_len = 0;
255     size_t len          = 0;
256 
257     while (al && err == GRIB_SUCCESS) {
258         len = *buffer_len - unpacked_len;
259         err = grib_unpack_long(al->accessor, val + unpacked_len, &len);
260         unpacked_len += len;
261         al = al->next;
262     }
263 
264     *buffer_len = unpacked_len;
265     return err;
266 }
267 
grib_accessors_list_unpack_double(grib_accessors_list * al,double * val,size_t * buffer_len)268 int grib_accessors_list_unpack_double(grib_accessors_list* al, double* val, size_t* buffer_len)
269 {
270     int err             = GRIB_SUCCESS;
271     size_t unpacked_len = 0;
272     size_t len          = 0;
273 
274     while (al && err == GRIB_SUCCESS) {
275         len = *buffer_len - unpacked_len;
276         err = grib_unpack_double(al->accessor, val + unpacked_len, &len);
277         unpacked_len += len;
278         al = al->next;
279     }
280 
281     *buffer_len = unpacked_len;
282     return err;
283 }
284 
grib_accessors_list_unpack_string(grib_accessors_list * al,char ** val,size_t * buffer_len)285 int grib_accessors_list_unpack_string(grib_accessors_list* al, char** val, size_t* buffer_len)
286 {
287     int err             = GRIB_SUCCESS;
288     size_t unpacked_len = 0;
289     size_t len          = 0;
290 
291     while (al && err == GRIB_SUCCESS) {
292         len = *buffer_len - unpacked_len;
293         err = grib_unpack_string_array(al->accessor, val + unpacked_len, &len);
294         unpacked_len += len;
295         al = al->next;
296     }
297 
298     *buffer_len = unpacked_len;
299     return err;
300 }
301 
grib_unpack_long(grib_accessor * a,long * v,size_t * len)302 int grib_unpack_long(grib_accessor* a, long* v, size_t* len)
303 {
304     grib_accessor_class* c = a->cclass;
305     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is unpacking (long)",(a->parent->owner)?(a->parent->owner->name):"root", a->name ); */
306     while (c) {
307         if (c->unpack_long) {
308             return c->unpack_long(a, v, len);
309         }
310         c = c->super ? *(c->super) : NULL;
311     }
312     DebugAssert(0);
313     return 0;
314 }
315 
grib_accessor_get_native_type(grib_accessor * a)316 long grib_accessor_get_native_type(grib_accessor* a)
317 {
318     grib_accessor_class* c = NULL;
319     if (a)
320         c = a->cclass;
321 
322     while (c) {
323         if (c->get_native_type)
324             return c->get_native_type(a);
325         c = c->super ? *(c->super) : NULL;
326     }
327     DebugAssert(0);
328     return 0;
329 }
330 
grib_get_next_position_offset(grib_accessor * a)331 long grib_get_next_position_offset(grib_accessor* a)
332 {
333     grib_accessor_class* c = NULL;
334     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is checking next (long)",(a->parent->owner)?(a->parent->owner->name):"root", a->name ); */
335     if (a)
336         c = a->cclass;
337 
338     while (c) {
339         if (c->next_offset)
340             return c->next_offset(a);
341         c = c->super ? *(c->super) : NULL;
342     }
343     DebugAssert(0);
344     return 0;
345 }
346 
grib_string_length(grib_accessor * a)347 long grib_string_length(grib_accessor* a)
348 {
349     grib_accessor_class* c = NULL;
350     if (a)
351         c = a->cclass;
352 
353     while (c) {
354         if (c->string_length)
355             return c->string_length(a);
356         c = c->super ? *(c->super) : NULL;
357     }
358     DebugAssert(0);
359     return 0;
360 }
361 
grib_byte_offset(grib_accessor * a)362 long grib_byte_offset(grib_accessor* a)
363 {
364     grib_accessor_class* c = NULL;
365     if (a)
366         c = a->cclass;
367 
368     while (c) {
369         if (c->byte_offset)
370             return c->byte_offset(a);
371         c = c->super ? *(c->super) : NULL;
372     }
373     DebugAssert(0);
374     return 0;
375 }
376 
grib_byte_count(grib_accessor * a)377 long grib_byte_count(grib_accessor* a)
378 {
379     grib_accessor_class* c = NULL;
380     if (a)
381         c = a->cclass;
382 
383     while (c) {
384         if (c->byte_count)
385             return c->byte_count(a);
386         c = c->super ? *(c->super) : NULL;
387     }
388     DebugAssert(0);
389     return 0;
390 }
391 
grib_value_count(grib_accessor * a,long * count)392 int grib_value_count(grib_accessor* a, long* count)
393 {
394     grib_accessor_class* c = NULL;
395     int err                = 0;
396     if (a)
397         c = a->cclass;
398 
399     while (c) {
400         if (c->value_count) {
401             err = c->value_count(a, count);
402             return err;
403         }
404         c = c->super ? *(c->super) : NULL;
405     }
406     DebugAssert(0);
407     return 0;
408 }
409 
grib_accessors_list_value_count(grib_accessors_list * al,size_t * count)410 int grib_accessors_list_value_count(grib_accessors_list* al, size_t* count)
411 {
412     long lcount = 0;
413     *count      = 0;
414     while (al) {
415         grib_value_count(al->accessor, &lcount);
416         *count += lcount;
417         al = al->next;
418     }
419     return 0;
420 }
421 
grib_accessor_notify_change(grib_accessor * a,grib_accessor * changed)422 int grib_accessor_notify_change(grib_accessor* a, grib_accessor* changed)
423 {
424     grib_accessor_class* c = NULL;
425     if (a)
426         c = a->cclass;
427 
428     while (c) {
429         if (c->notify_change)
430             return c->notify_change(a, changed);
431         c = c->super ? *(c->super) : NULL;
432     }
433     if (a && a->cclass)
434         printf("notify_change not implemented for %s %s\n", a->cclass->name, a->name);
435     DebugAssert(0);
436     return 0;
437 }
438 
439 /* For this one, ALL init are called */
440 
init_accessor(grib_accessor_class * c,grib_accessor * a,const long len,grib_arguments * args)441 static void init_accessor(grib_accessor_class* c, grib_accessor* a, const long len, grib_arguments* args)
442 {
443     if (c) {
444         grib_accessor_class* s = c->super ? *(c->super) : NULL;
445         init_accessor(s, a, len, args);
446         if (c->init)
447             c->init(a, len, args);
448     }
449 }
450 
grib_init_accessor(grib_accessor * a,const long len,grib_arguments * args)451 void grib_init_accessor(grib_accessor* a, const long len, grib_arguments* args)
452 {
453     init_accessor(a->cclass, a, len, args);
454 }
455 
456 #if 0
457 static void post_init_accessor(grib_accessor_class* c,grib_accessor* a)
458 {
459     if(c) {
460         grib_accessor_class *s = c->super ? *(c->super) : NULL;
461         post_init_accessor(s,a);
462         if(c->post_init) c->post_init(a);
463     }
464 }
465 #endif
466 
467 /* For this one, ALL destroy are called */
468 
grib_accessor_delete(grib_context * ct,grib_accessor * a)469 void grib_accessor_delete(grib_context* ct, grib_accessor* a)
470 {
471     grib_accessor_class* c = a->cclass;
472     while (c) {
473         grib_accessor_class* s = c->super ? *(c->super) : NULL;
474         /*printf("grib_accessor_delete: before destroy a=%p c->name=%s ==> a->name=%s\n", (void*)a, c->name, a->name);*/
475         if (c->destroy) {
476             c->destroy(ct, a);
477         }
478         c = s;
479     }
480     /*printf("grib_accessor_delete before free a=%p\n", (void*)a);*/
481     grib_context_free(ct, a);
482 }
483 
grib_accessor_clone(grib_accessor * a,grib_section * s,int * err)484 grib_accessor* grib_accessor_clone(grib_accessor* a, grib_section* s, int* err)
485 {
486     grib_accessor_class* c = a->cclass;
487     grib_context* ct       = a->context;
488     while (c) {
489         grib_accessor_class* super = c->super ? *(c->super) : NULL;
490         grib_context_log(ct, GRIB_LOG_DEBUG, "clone %s ==> %s", c->name, a->name);
491         if (c->make_clone) {
492             return c->make_clone(a, s, err);
493         }
494         c = super;
495     }
496     return 0;
497 }
498 
grib_update_size(grib_accessor * a,size_t len)499 void grib_update_size(grib_accessor* a, size_t len)
500 {
501     grib_accessor_class* c = a->cclass;
502     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (double) %g",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?(*v):0); */
503     while (c) {
504         if (c->update_size) {
505             c->update_size(a, len);
506             return;
507         }
508         c = c->super ? *(c->super) : NULL;
509     }
510     DebugAssert(0);
511 }
512 
grib_nearest_smaller_value(grib_accessor * a,double val,double * nearest)513 int grib_nearest_smaller_value(grib_accessor* a, double val, double* nearest)
514 {
515     grib_accessor_class* c = a->cclass;
516     while (c) {
517         if (c->nearest_smaller_value) {
518             return c->nearest_smaller_value(a, val, nearest);
519         }
520         c = c->super ? *(c->super) : NULL;
521     }
522     DebugAssert(0);
523     return 0;
524 }
525 
526 
grib_preferred_size(grib_accessor * a,int from_handle)527 size_t grib_preferred_size(grib_accessor* a, int from_handle)
528 {
529     grib_accessor_class* c = a->cclass;
530     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (long) %d",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?(*v):0); */
531     while (c) {
532         if (c->preferred_size) {
533             return c->preferred_size(a, from_handle);
534         }
535         c = c->super ? *(c->super) : NULL;
536     }
537     DebugAssert(0);
538     return 0;
539 }
540 
grib_next_accessor(grib_accessor * a)541 grib_accessor* grib_next_accessor(grib_accessor* a)
542 {
543     grib_accessor_class* c = a->cclass;
544     while (c) {
545         if (c->next) {
546             return c->next(a, 1);
547         }
548         c = c->super ? *(c->super) : NULL;
549     }
550     DebugAssert(0);
551     return 0;
552 }
553 
grib_resize(grib_accessor * a,size_t new_size)554 void grib_resize(grib_accessor* a, size_t new_size)
555 {
556     grib_accessor_class* c = a->cclass;
557     /*grib_context_log(a->context, GRIB_LOG_DEBUG, "(%s)%s is packing (long) %d",(a->parent->owner)?(a->parent->owner->name):"root", a->name ,v?(*v):0); */
558     while (c) {
559         if (c->resize) {
560             c->resize(a, new_size);
561             return;
562         }
563         c = c->super ? *(c->super) : NULL;
564     }
565     DebugAssert(0);
566     return;
567 }
568 
grib_compare_accessors(grib_accessor * a1,grib_accessor * a2,int compare_flags)569 int grib_compare_accessors(grib_accessor* a1, grib_accessor* a2, int compare_flags)
570 {
571     int ret                 = 0;
572     long type1              = 0;
573     long type2              = 0;
574     int type_mismatch       = 0;
575     grib_accessor_class* c1 = NULL;
576 
577     if ((compare_flags & GRIB_COMPARE_NAMES) && grib_inline_strcmp(a1->name, a2->name))
578         return GRIB_NAME_MISMATCH;
579 
580     if (compare_flags & GRIB_COMPARE_TYPES) {
581         type1 = grib_accessor_get_native_type(a1);
582         type2 = grib_accessor_get_native_type(a2);
583 
584         type_mismatch = type1 != type2 ? 1 : 0;
585     }
586 
587     ret = GRIB_UNABLE_TO_COMPARE_ACCESSORS;
588     c1  = a1->cclass;
589     while (c1) {
590         if (c1->compare) {
591             ret = c1->compare(a1, a2);
592             break;
593         }
594         c1 = c1->super ? *(c1->super) : NULL;
595     }
596 
597     if (ret == GRIB_VALUE_MISMATCH && type_mismatch)
598         ret = GRIB_TYPE_AND_VALUE_MISMATCH;
599 
600     return ret;
601 }
602 
grib_get_type_name(int type)603 const char* grib_get_type_name(int type)
604 {
605     switch (type) {
606         case GRIB_TYPE_LONG:
607             return "long";
608         case GRIB_TYPE_STRING:
609             return "string";
610         case GRIB_TYPE_BYTES:
611             return "bytes";
612         case GRIB_TYPE_DOUBLE:
613             return "double";
614         case GRIB_TYPE_LABEL:
615             return "label";
616         case GRIB_TYPE_SECTION:
617             return "section";
618     }
619     return "unknown";
620 }
621 
622 /*
623 int grib_accessor_clear_attributes(grib_accessor* a)
624 {
625     int id;
626     for (id=0;id<MAX_ACCESSOR_ATTRIBUTES;id++) {
627         a->attributes[id]=NULL;
628     }
629     return 0;
630 }
631  */
632 
grib_accessor_add_attribute(grib_accessor * a,grib_accessor * attr,int nest_if_clash)633 int grib_accessor_add_attribute(grib_accessor* a, grib_accessor* attr, int nest_if_clash)
634 {
635     int id              = 0;
636     int idx             = 0;
637     grib_accessor* same = NULL;
638     grib_accessor* aloc = a;
639 
640     if (grib_accessor_has_attributes(a)) {
641         same = _grib_accessor_get_attribute(a, attr->name, &id);
642     }
643 
644     if (same) {
645         if (nest_if_clash == 0)
646             return GRIB_ATTRIBUTE_CLASH;
647         aloc = same;
648     }
649 
650     for (id = 0; id < MAX_ACCESSOR_ATTRIBUTES; id++) {
651         if (aloc->attributes[id] == NULL) {
652             /* attr->parent=a->parent; */
653             aloc->attributes[id]      = attr;
654             attr->parent_as_attribute = aloc;
655             if (aloc->same)
656                 attr->same = _grib_accessor_get_attribute(aloc->same, attr->name, &idx);
657 
658             grib_context_log(a->context, GRIB_LOG_DEBUG, "added attribute %s->%s", a->name, attr->name);
659             return GRIB_SUCCESS;
660         }
661     }
662     return GRIB_TOO_MANY_ATTRIBUTES;
663 }
664 
grib_accessor_replace_attribute(grib_accessor * a,grib_accessor * attr)665 int grib_accessor_replace_attribute(grib_accessor* a, grib_accessor* attr)
666 {
667     int id  = 0;
668     int idx = 0;
669     if (_grib_accessor_get_attribute(a, attr->name, &id) != NULL) {
670         grib_accessor_delete(a->context, a->attributes[id]);
671         a->attributes[id]         = attr;
672         attr->parent_as_attribute = a;
673         if (a->same)
674             attr->same = _grib_accessor_get_attribute(a->same, attr->name, &idx);
675     }
676     else {
677         grib_accessor_add_attribute(a, attr, 0);
678     }
679     return GRIB_SUCCESS;
680 }
681 
grib_accessor_delete_attribute(grib_accessor * a,const char * name)682 int grib_accessor_delete_attribute(grib_accessor* a, const char* name)
683 {
684     int id = 0;
685     if (_grib_accessor_get_attribute(a, name, &id) != NULL) {
686         grib_accessor_delete(a->context, a->attributes[id]);
687         a->attributes[id] = NULL;
688         return GRIB_SUCCESS;
689     }
690     else {
691         return GRIB_NOT_FOUND;
692     }
693 }
694 
grib_accessor_get_attribute_by_index(grib_accessor * a,int index)695 grib_accessor* grib_accessor_get_attribute_by_index(grib_accessor* a, int index)
696 {
697     if (index < MAX_ACCESSOR_ATTRIBUTES)
698         return a->attributes[index];
699 
700     return NULL;
701 }
702 
grib_accessor_get_name(grib_accessor * a)703 const char* grib_accessor_get_name(grib_accessor* a)
704 {
705     return a->name;
706 }
707 
_grib_accessor_get_attribute(grib_accessor * a,const char * name,int * index)708 grib_accessor* _grib_accessor_get_attribute(grib_accessor* a, const char* name, int* index)
709 {
710     int i = 0;
711     while (i < MAX_ACCESSOR_ATTRIBUTES && a->attributes[i]) {
712         if (!grib_inline_strcmp(a->attributes[i]->name, name)) {
713             *index = i;
714             return a->attributes[i];
715         }
716         i++;
717     }
718     return NULL;
719 }
720 
grib_accessor_has_attributes(grib_accessor * a)721 int grib_accessor_has_attributes(grib_accessor* a)
722 {
723     return a->attributes[0] ? 1 : 0;
724 }
725 
grib_accessor_get_attribute(grib_accessor * a,const char * name)726 grib_accessor* grib_accessor_get_attribute(grib_accessor* a, const char* name)
727 {
728     int index                  = 0;
729     const char* p              = 0;
730     char* basename             = NULL;
731     const char* attribute_name = NULL;
732     grib_accessor* acc         = NULL;
733     p                          = name;
734     while (*(p + 1) != '\0' && (*p != '-' || *(p + 1) != '>'))
735         p++;
736     if (*(p + 1) == '\0') {
737         return _grib_accessor_get_attribute(a, name, &index);
738     }
739     else {
740         size_t size    = p - name;
741         attribute_name = p + 2;
742         basename       = (char*)grib_context_malloc_clear(a->context, size + 1);
743         basename       = (char*)memcpy(basename, name, size);
744         acc            = _grib_accessor_get_attribute(a, basename, &index);
745         grib_context_free(a->context, basename);
746         if (acc)
747             return grib_accessor_get_attribute(acc, attribute_name);
748         else
749             return NULL;
750     }
751 }
752 
grib_accessors_list_create(grib_context * c)753 grib_accessors_list* grib_accessors_list_create(grib_context* c)
754 {
755     return (grib_accessors_list*)grib_context_malloc_clear(c, sizeof(grib_accessors_list));
756 }
757 
grib_accessors_list_push(grib_accessors_list * al,grib_accessor * a,int rank)758 void grib_accessors_list_push(grib_accessors_list* al, grib_accessor* a, int rank)
759 {
760     grib_accessors_list* last;
761     grib_context* c = a->context;
762 
763     last = grib_accessors_list_last(al);
764     if (last && last->accessor) {
765         last->next           = (grib_accessors_list*)grib_context_malloc_clear(c, sizeof(grib_accessors_list));
766         last->next->accessor = a;
767         last->next->prev     = last;
768         last->next->rank     = rank;
769         al->last             = last->next;
770     }
771     else {
772         al->accessor = a;
773         al->rank     = rank;
774         al->last     = al;
775     }
776 }
777 
grib_accessors_list_last(grib_accessors_list * al)778 grib_accessors_list* grib_accessors_list_last(grib_accessors_list* al)
779 {
780     /*grib_accessors_list* last=al;*/
781     /*grib_accessors_list* next=al->next;*/
782 
783     /*
784     while(next) {
785       last=next;
786       next=last->next;
787     }
788      */
789     return al->last;
790 }
791 
grib_accessors_list_find(grib_accessors_list * al,grib_accessor * a)792 grib_accessors_list* grib_accessors_list_find(grib_accessors_list* al, grib_accessor* a)
793 {
794     grib_accessors_list* last = al;
795     grib_accessors_list* next = al->next;
796 
797     while (next) {
798         if (last->accessor == a)
799             return last;
800         last = next;
801         next = last->next;
802     }
803 
804     return NULL;
805 }
806 
grib_accessors_list_delete(grib_context * c,grib_accessors_list * al)807 void grib_accessors_list_delete(grib_context* c, grib_accessors_list* al)
808 {
809     grib_accessors_list* tmp;
810 
811     while (al) {
812         tmp = al->next;
813         /*grib_accessor_delete(c, al->accessor);*/
814         grib_context_free(c, al);
815         al = tmp;
816     }
817 }
818 
819 
820 #if 0
821 void grib_print_accessor_flags(const grib_accessor* acc)
822 {
823     const unsigned long f = acc->flags;
824     if (f & GRIB_ACCESSOR_FLAG_READ_ONLY)        printf("READ_ONLY ");
825     if (f & GRIB_ACCESSOR_FLAG_DUMP)             printf("DUMP ");
826     if (f & GRIB_ACCESSOR_FLAG_EDITION_SPECIFIC) printf("EDITION_SPECIFIC ");
827     if (f & GRIB_ACCESSOR_FLAG_CAN_BE_MISSING)   printf("CAN_BE_MISSING ");
828     if (f & GRIB_ACCESSOR_FLAG_LOWERCASE)        printf("LOWERCASE ");
829     if (f & GRIB_ACCESSOR_FLAG_HIDDEN)           printf("HIDDEN ");
830     /* TODO: the rest */
831 }
832 #endif
833