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 #include "grib_api_internal.h"
12 #include <ctype.h>
13 /*
14 This is used by make_class.pl
15
16 START_CLASS_DEF
17 CLASS = dumper
18 IMPLEMENTS = dump_long;dump_bits
19 IMPLEMENTS = dump_double;dump_string;dump_string_array
20 IMPLEMENTS = dump_bytes;dump_values
21 IMPLEMENTS = dump_label;dump_section
22 IMPLEMENTS = init;destroy
23 IMPLEMENTS = header;footer
24 MEMBERS = long section_offset
25 MEMBERS = long empty
26 MEMBERS = long end
27 MEMBERS = long isLeaf
28 MEMBERS = long isAttribute
29 MEMBERS = grib_string_list* keys
30 END_CLASS_DEF
31
32 */
33
34
35 /* START_CLASS_IMP */
36
37 /*
38
39 Don't edit anything between START_CLASS_IMP and END_CLASS_IMP
40 Instead edit values between START_CLASS_DEF and END_CLASS_DEF
41 or edit "dumper.class" and rerun ./make_class.pl
42
43 */
44
45 static void init_class(grib_dumper_class*);
46 static int init(grib_dumper* d);
47 static int destroy(grib_dumper*);
48 static void dump_long(grib_dumper* d, grib_accessor* a, const char* comment);
49 static void dump_bits(grib_dumper* d, grib_accessor* a, const char* comment);
50 static void dump_double(grib_dumper* d, grib_accessor* a, const char* comment);
51 static void dump_string(grib_dumper* d, grib_accessor* a, const char* comment);
52 static void dump_string_array(grib_dumper* d, grib_accessor* a, const char* comment);
53 static void dump_bytes(grib_dumper* d, grib_accessor* a, const char* comment);
54 static void dump_values(grib_dumper* d, grib_accessor* a);
55 static void dump_label(grib_dumper* d, grib_accessor* a, const char* comment);
56 static void dump_section(grib_dumper* d, grib_accessor* a, grib_block_of_accessors* block);
57 static void header(grib_dumper*, grib_handle*);
58 static void footer(grib_dumper*, grib_handle*);
59
60 typedef struct grib_dumper_bufr_encode_python
61 {
62 grib_dumper dumper;
63 /* Members defined in bufr_encode_python */
64 long section_offset;
65 long empty;
66 long end;
67 long isLeaf;
68 long isAttribute;
69 grib_string_list* keys;
70 } grib_dumper_bufr_encode_python;
71
72
73 static grib_dumper_class _grib_dumper_class_bufr_encode_python = {
74 0, /* super */
75 "bufr_encode_python", /* name */
76 sizeof(grib_dumper_bufr_encode_python), /* size */
77 0, /* inited */
78 &init_class, /* init_class */
79 &init, /* init */
80 &destroy, /* free mem */
81 &dump_long, /* dump long */
82 &dump_double, /* dump double */
83 &dump_string, /* dump string */
84 &dump_string_array, /* dump string array */
85 &dump_label, /* dump labels */
86 &dump_bytes, /* dump bytes */
87 &dump_bits, /* dump bits */
88 &dump_section, /* dump section */
89 &dump_values, /* dump values */
90 &header, /* header */
91 &footer, /* footer */
92 };
93
94 grib_dumper_class* grib_dumper_class_bufr_encode_python = &_grib_dumper_class_bufr_encode_python;
95
96 /* END_CLASS_IMP */
97 static void dump_attributes(grib_dumper* d, grib_accessor* a, const char* prefix);
98
99 /* Note: A fast cut-down version of strcmp which does NOT return -1 */
100 /* 0 means input strings are equal and 1 means not equal */
grib_inline_strcmp(const char * a,const char * b)101 GRIB_INLINE static int grib_inline_strcmp(const char* a, const char* b)
102 {
103 if (*a != *b)
104 return 1;
105 while ((*a != 0 && *b != 0) && *(a) == *(b)) {
106 a++;
107 b++;
108 }
109 return (*a == 0 && *b == 0) ? 0 : 1;
110 }
111
112 typedef struct string_count string_count;
113 struct string_count
114 {
115 char* value;
116 int count;
117 string_count* next;
118 };
119
120 static int depth = 0;
121
init_class(grib_dumper_class * c)122 static void init_class(grib_dumper_class* c) {}
123
init(grib_dumper * d)124 static int init(grib_dumper* d)
125 {
126 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
127 grib_context* c = d->context;
128 self->section_offset = 0;
129 self->empty = 1;
130 d->count = 1;
131 self->isLeaf = 0;
132 self->isAttribute = 0;
133 self->keys = (grib_string_list*)grib_context_malloc_clear(c, sizeof(grib_string_list));
134
135 return GRIB_SUCCESS;
136 }
137
destroy(grib_dumper * d)138 static int destroy(grib_dumper* d)
139 {
140 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
141 grib_string_list* next = self->keys;
142 grib_string_list* cur = NULL;
143 grib_context* c = d->context;
144 while (next) {
145 cur = next;
146 next = next->next;
147 grib_context_free(c, cur->value);
148 grib_context_free(c, cur);
149 }
150 return GRIB_SUCCESS;
151 }
152
lval_to_string(grib_context * c,long v)153 static char* lval_to_string(grib_context* c, long v)
154 {
155 char* sval = (char*)grib_context_malloc_clear(c, sizeof(char) * 40);
156 if (v == GRIB_MISSING_LONG)
157 sprintf(sval, "CODES_MISSING_LONG");
158 else
159 sprintf(sval, "%ld", v);
160 return sval;
161 }
dval_to_string(const grib_context * c,double v)162 static char* dval_to_string(const grib_context* c, double v)
163 {
164 char* sval = (char*)grib_context_malloc_clear(c, sizeof(char) * 40);
165 if (v == GRIB_MISSING_DOUBLE)
166 sprintf(sval, "CODES_MISSING_DOUBLE");
167 else
168 sprintf(sval, "%.18e", v);
169 return sval;
170 }
171
dump_values(grib_dumper * d,grib_accessor * a)172 static void dump_values(grib_dumper* d, grib_accessor* a)
173 {
174 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
175 double value = 0;
176 size_t size = 0, size2 = 0;
177 double* values = NULL;
178 int err = 0;
179 int i, r, icount;
180 int cols = 2;
181 long count = 0;
182 char* sval;
183 grib_context* c = a->context;
184 grib_handle* h = grib_handle_of_accessor(a);
185
186 if ((a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0 || (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) != 0)
187 return;
188
189 grib_value_count(a, &count);
190 size = size2 = count;
191
192 if (size > 1) {
193 values = (double*)grib_context_malloc_clear(c, sizeof(double) * size);
194 err = grib_unpack_double(a, values, &size2);
195 }
196 else {
197 err = grib_unpack_double(a, &value, &size2);
198 }
199 Assert(size2 == size);
200
201 self->empty = 0;
202
203 if (size > 1) {
204 fprintf(self->dumper.out, " rvalues = (");
205
206 icount = 0;
207 for (i = 0; i < size - 1; ++i) {
208 if (icount > cols || i == 0) {
209 fprintf(self->dumper.out, "\n ");
210 icount = 0;
211 }
212 sval = dval_to_string(c, values[i]);
213 fprintf(self->dumper.out, "%s, ", sval);
214 grib_context_free(c, sval);
215 icount++;
216 }
217 if (icount > cols || i == 0) {
218 fprintf(self->dumper.out, "\n ");
219 }
220 sval = dval_to_string(c, values[i]);
221 fprintf(self->dumper.out, "%s", sval);
222 grib_context_free(c, sval);
223
224 depth -= 2;
225 /* Note: In Python to make a tuple with one element, you need the trailing comma */
226 if (size > 4)
227 fprintf(self->dumper.out, ",) # %lu values\n", (unsigned long)size);
228 else
229 fprintf(self->dumper.out, ",)\n");
230 grib_context_free(c, values);
231
232 if ((r = compute_bufr_key_rank(h, self->keys, a->name)) != 0)
233 fprintf(self->dumper.out, " codes_set_array(ibufr, '#%d#%s', rvalues)\n", r, a->name);
234 else
235 fprintf(self->dumper.out, " codes_set_array(ibufr, '%s', rvalues)\n", a->name);
236 }
237 else {
238 r = compute_bufr_key_rank(h, self->keys, a->name);
239 sval = dval_to_string(c, value);
240 if (r != 0)
241 fprintf(self->dumper.out, " codes_set(ibufr, '#%d#%s', %s)\n", r, a->name, sval);
242 else
243 fprintf(self->dumper.out, " codes_set(ibufr, '%s', %s)\n", a->name, sval);
244 grib_context_free(c, sval);
245 }
246
247 if (self->isLeaf == 0) {
248 char* prefix;
249 int dofree = 0;
250
251 if (r != 0) {
252 prefix = (char*)grib_context_malloc_clear(c, sizeof(char) * (strlen(a->name) + 10));
253 dofree = 1;
254 sprintf(prefix, "#%d#%s", r, a->name);
255 }
256 else
257 prefix = (char*)a->name;
258
259 dump_attributes(d, a, prefix);
260 if (dofree)
261 grib_context_free(c, prefix);
262 depth -= 2;
263 }
264
265 (void)err; /* TODO */
266 }
267
dump_values_attribute(grib_dumper * d,grib_accessor * a,const char * prefix)268 static void dump_values_attribute(grib_dumper* d, grib_accessor* a, const char* prefix)
269 {
270 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
271 double value = 0;
272 size_t size = 0, size2 = 0;
273 double* values = NULL;
274 int err = 0, i = 0, icount = 0;
275 int cols = 2;
276 long count = 0;
277 char* sval;
278 grib_context* c = a->context;
279
280 if ((a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0 || (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) != 0)
281 return;
282
283 grib_value_count(a, &count);
284 size = size2 = count;
285
286 if (size > 1) {
287 values = (double*)grib_context_malloc_clear(c, sizeof(double) * size);
288 err = grib_unpack_double(a, values, &size2);
289 }
290 else {
291 err = grib_unpack_double(a, &value, &size2);
292 }
293 Assert(size2 == size);
294
295 self->empty = 0;
296
297 if (size > 1) {
298 fprintf(self->dumper.out, " rvalues = (");
299
300 icount = 0;
301 for (i = 0; i < size - 1; ++i) {
302 if (icount > cols || i == 0) {
303 fprintf(self->dumper.out, "\n ");
304 icount = 0;
305 }
306 sval = dval_to_string(c, values[i]);
307 fprintf(self->dumper.out, "%s, ", sval);
308 grib_context_free(c, sval);
309 icount++;
310 }
311 if (icount > cols || i == 0) {
312 fprintf(self->dumper.out, "\n ");
313 }
314 sval = dval_to_string(c, values[i]);
315 fprintf(self->dumper.out, "%s", sval);
316 grib_context_free(c, sval);
317
318 depth -= 2;
319 /* Note: In python to make a tuple with one element, you need the trailing comma */
320 if (size > 4)
321 fprintf(self->dumper.out, ",) # %lu values\n", (unsigned long)size);
322 else
323 fprintf(self->dumper.out, ",)\n");
324 grib_context_free(c, values);
325
326 fprintf(self->dumper.out, " codes_set_array(ibufr, '%s->%s' \n, rvalues)\n", prefix, a->name);
327 }
328 else {
329 sval = dval_to_string(c, value);
330 fprintf(self->dumper.out, " codes_set(ibufr, '%s->%s' \n,%s)\n", prefix, a->name, sval);
331 grib_context_free(c, sval);
332 }
333
334 if (self->isLeaf == 0) {
335 char* prefix1;
336
337 prefix1 = (char*)grib_context_malloc_clear(c, sizeof(char) * (strlen(a->name) + strlen(prefix) + 5));
338 sprintf(prefix1, "%s->%s", prefix, a->name);
339
340 dump_attributes(d, a, prefix1);
341
342 grib_context_free(c, prefix1);
343 depth -= 2;
344 }
345
346 (void)err; /* TODO */
347 }
348
is_hidden(grib_accessor * a)349 static int is_hidden(grib_accessor* a)
350 {
351 return ( (a->flags & GRIB_ACCESSOR_FLAG_HIDDEN) != 0 );
352 }
353
dump_long(grib_dumper * d,grib_accessor * a,const char * comment)354 static void dump_long(grib_dumper* d, grib_accessor* a, const char* comment)
355 {
356 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
357 long value = 0;
358 size_t size = 0, size2 = 0;
359 long* values = NULL;
360 int err = 0, i = 0, r = 0, icount = 0;
361 int cols = 4;
362 long count = 0;
363 char* sval = NULL;
364 grib_context* c = a->context;
365 grib_handle* h = grib_handle_of_accessor(a);
366 int doing_unexpandedDescriptors = 0;
367
368 if ((a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0) { /* key does not have the dump attribute */
369 int skip = 1;
370 /* See ECC-1107 */
371 if (!is_hidden(a) && strcmp(a->name, "messageLength") == 0) skip = 0;
372 if (skip) return;
373 }
374
375 doing_unexpandedDescriptors = (strcmp(a->name, "unexpandedDescriptors") == 0);
376 grib_value_count(a, &count);
377 size = size2 = count;
378
379 if ((a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) != 0) {
380 if (self->isLeaf == 0) {
381 char* prefix;
382 int dofree = 0;
383
384 r = compute_bufr_key_rank(h, self->keys, a->name);
385 if (r != 0) {
386 prefix = (char*)grib_context_malloc_clear(c, sizeof(char) * (strlen(a->name) + 10));
387 dofree = 1;
388 sprintf(prefix, "#%d#%s", r, a->name);
389 }
390 else
391 prefix = (char*)a->name;
392
393 dump_attributes(d, a, prefix);
394 if (dofree)
395 grib_context_free(c, prefix);
396 depth -= 2;
397 }
398 return;
399 }
400
401 if (size > 1) {
402 values = (long*)grib_context_malloc_clear(a->context, sizeof(long) * size);
403 err = grib_unpack_long(a, values, &size2);
404 }
405 else {
406 err = grib_unpack_long(a, &value, &size2);
407 }
408 Assert(size2 == size);
409
410 self->empty = 0;
411
412 if (size > 1) {
413 fprintf(self->dumper.out, " ivalues = (");
414 icount = 0;
415 for (i = 0; i < size - 1; i++) {
416 if (icount > cols || i == 0) {
417 fprintf(self->dumper.out, "\n ");
418 icount = 0;
419 }
420 fprintf(self->dumper.out, "%ld, ", values[i]);
421 icount++;
422 }
423 if (icount > cols || i == 0) {
424 fprintf(self->dumper.out, "\n ");
425 }
426 fprintf(self->dumper.out, "%ld", values[i]);
427
428 depth -= 2;
429 /* Note: In python to make a tuple with one element, you need the trailing comma */
430 if (size > 4)
431 fprintf(self->dumper.out, ",) # %lu values\n", (unsigned long)size);
432 else
433 fprintf(self->dumper.out, ",)\n");
434 grib_context_free(a->context, values);
435
436 if ((r = compute_bufr_key_rank(h, self->keys, a->name)) != 0) {
437 fprintf(self->dumper.out, " codes_set_array(ibufr, '#%d#%s', ivalues)\n", r, a->name);
438 }
439 else {
440 if (doing_unexpandedDescriptors) {
441 fprintf(self->dumper.out, "\n # Create the structure of the data section\n");
442 /* fprintf(self->dumper.out," codes_set(ibufr, 'skipExtraKeyAttributes', 1)\n"); */
443 }
444 fprintf(self->dumper.out, " codes_set_array(ibufr, '%s', ivalues)\n", a->name);
445 if (doing_unexpandedDescriptors)
446 fprintf(self->dumper.out, "\n");
447 }
448 }
449 else {
450 r = compute_bufr_key_rank(h, self->keys, a->name);
451 sval = lval_to_string(c, value);
452 if (r != 0) {
453 fprintf(self->dumper.out, " codes_set(ibufr, '#%d#%s', ", r, a->name);
454 }
455 else {
456 if (doing_unexpandedDescriptors) {
457 fprintf(self->dumper.out, "\n # Create the structure of the data section\n");
458 /* fprintf(self->dumper.out," codes_set(ibufr, 'skipExtraKeyAttributes', 1)\n"); */
459 }
460 fprintf(self->dumper.out, " codes_set(ibufr, '%s', ", a->name);
461 }
462
463 fprintf(self->dumper.out, "%s)\n", sval);
464 grib_context_free(c, sval);
465 if (doing_unexpandedDescriptors)
466 fprintf(self->dumper.out, "\n");
467 }
468
469 if (self->isLeaf == 0) {
470 char* prefix;
471 int dofree = 0;
472
473 if (r != 0) {
474 prefix = (char*)grib_context_malloc_clear(c, sizeof(char) * (strlen(a->name) + 10));
475 dofree = 1;
476 sprintf(prefix, "#%d#%s", r, a->name);
477 }
478 else
479 prefix = (char*)a->name;
480
481 dump_attributes(d, a, prefix);
482 if (dofree)
483 grib_context_free(c, prefix);
484 depth -= 2;
485 }
486 (void)err; /* TODO */
487 }
488
dump_long_attribute(grib_dumper * d,grib_accessor * a,const char * prefix)489 static void dump_long_attribute(grib_dumper* d, grib_accessor* a, const char* prefix)
490 {
491 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
492 long value = 0;
493 size_t size = 0, size2 = 0;
494 long* values = NULL;
495 int err = 0, i = 0, icount = 0;
496 int cols = 4;
497 long count = 0;
498 grib_context* c = a->context;
499
500 if ((a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0 || (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) != 0)
501 return;
502
503 grib_value_count(a, &count);
504 size = size2 = count;
505
506 if (size > 1) {
507 values = (long*)grib_context_malloc_clear(a->context, sizeof(long) * size);
508 err = grib_unpack_long(a, values, &size2);
509 }
510 else {
511 err = grib_unpack_long(a, &value, &size2);
512 }
513 Assert(size2 == size);
514
515 self->empty = 0;
516
517 if (size > 1) {
518 fprintf(self->dumper.out, " ivalues = (");
519 icount = 0;
520 for (i = 0; i < size - 1; i++) {
521 if (icount > cols || i == 0) {
522 fprintf(self->dumper.out, " \n ");
523 icount = 0;
524 }
525 fprintf(self->dumper.out, "%ld, ", values[i]);
526 icount++;
527 }
528 if (icount > cols || i == 0) {
529 fprintf(self->dumper.out, " \n ");
530 }
531 fprintf(self->dumper.out, "%ld ", values[i]);
532
533 depth -= 2;
534 /* Note: In python to make a tuple with one element, you need the trailing comma */
535 if (size > 4)
536 fprintf(self->dumper.out, ",) # %lu values\n", (unsigned long)size);
537 else
538 fprintf(self->dumper.out, ",)\n");
539 grib_context_free(a->context, values);
540
541 fprintf(self->dumper.out, " codes_set_array(ibufr, '%s->%s', ivalues)\n", prefix, a->name);
542 }
543 else {
544 char* sval = lval_to_string(c, value);
545 fprintf(self->dumper.out, " codes_set(ibufr, '%s->%s', ", prefix, a->name);
546 fprintf(self->dumper.out, "%s)\n", sval);
547 grib_context_free(c, sval);
548 }
549
550 if (self->isLeaf == 0) {
551 char* prefix1;
552
553 prefix1 = (char*)grib_context_malloc_clear(c, sizeof(char) * (strlen(a->name) + strlen(prefix) + 5));
554 sprintf(prefix1, "%s->%s", prefix, a->name);
555
556 dump_attributes(d, a, prefix1);
557
558 grib_context_free(c, prefix1);
559 depth -= 2;
560 }
561 (void)err; /* TODO */
562 }
563
dump_bits(grib_dumper * d,grib_accessor * a,const char * comment)564 static void dump_bits(grib_dumper* d, grib_accessor* a, const char* comment)
565 {
566 }
567
dump_double(grib_dumper * d,grib_accessor * a,const char * comment)568 static void dump_double(grib_dumper* d, grib_accessor* a, const char* comment)
569 {
570 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
571 double value;
572 size_t size = 1;
573 int r;
574 char* sval;
575 grib_handle* h = grib_handle_of_accessor(a);
576 grib_context* c = h->context;
577
578 if ((a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0 || (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) != 0)
579 return;
580
581 grib_unpack_double(a, &value, &size);
582 self->empty = 0;
583
584 r = compute_bufr_key_rank(h, self->keys, a->name);
585
586 sval = dval_to_string(c, value);
587 if (r != 0)
588 fprintf(self->dumper.out, " codes_set(ibufr, '#%d#%s', %s)\n", r, a->name, sval);
589 else
590 fprintf(self->dumper.out, " codes_set(ibufr, '%s', %s)\n", a->name, sval);
591 grib_context_free(c, sval);
592
593 if (self->isLeaf == 0) {
594 char* prefix;
595 int dofree = 0;
596
597 if (r != 0) {
598 prefix = (char*)grib_context_malloc_clear(c, sizeof(char) * (strlen(a->name) + 10));
599 dofree = 1;
600 sprintf(prefix, "#%d#%s", r, a->name);
601 }
602 else
603 prefix = (char*)a->name;
604
605 dump_attributes(d, a, prefix);
606 if (dofree)
607 grib_context_free(c, prefix);
608 depth -= 2;
609 }
610 }
611
dump_string_array(grib_dumper * d,grib_accessor * a,const char * comment)612 static void dump_string_array(grib_dumper* d, grib_accessor* a, const char* comment)
613 {
614 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
615 char** values;
616 size_t size = 0, i = 0;
617 grib_context* c = a->context;
618 int err = 0;
619 long count = 0;
620 int r = 0;
621 grib_handle* h = grib_handle_of_accessor(a);
622
623 if ((a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0 || (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) != 0)
624 return;
625
626 grib_value_count(a, &count);
627 size = count;
628 if (size == 1) {
629 dump_string(d, a, comment);
630 return;
631 }
632
633 fprintf(self->dumper.out, " svalues = (");
634
635 self->empty = 0;
636
637 values = (char**)grib_context_malloc_clear(c, size * sizeof(char*));
638 if (!values) {
639 grib_context_log(c, GRIB_LOG_FATAL, "unable to allocate %d bytes", (int)size);
640 return;
641 }
642
643 err = grib_unpack_string_array(a, values, &size);
644
645 for (i = 0; i < size - 1; i++) {
646 fprintf(self->dumper.out, " \"%s\", \n", values[i]);
647 }
648 fprintf(self->dumper.out, " \"%s\", )\n", values[i]);
649
650 if (self->isLeaf == 0) {
651 if ((r = compute_bufr_key_rank(h, self->keys, a->name)) != 0)
652 fprintf(self->dumper.out, " codes_set_array(ibufr, '#%d#%s', svalues)\n", r, a->name);
653 else
654 fprintf(self->dumper.out, " codes_set_array(ibufr, '%s', svalues)\n", a->name);
655 }
656
657 if (self->isLeaf == 0) {
658 char* prefix;
659 int dofree = 0;
660
661 if (r != 0) {
662 prefix = (char*)grib_context_malloc_clear(c, sizeof(char) * (strlen(a->name) + 10));
663 dofree = 1;
664 sprintf(prefix, "#%d#%s", r, a->name);
665 }
666 else
667 prefix = (char*)a->name;
668
669 dump_attributes(d, a, prefix);
670 if (dofree)
671 grib_context_free(c, prefix);
672 depth -= 2;
673 }
674 for (i=0; i<size; ++i) grib_context_free(c, values[i]);
675 grib_context_free(c, values);
676 (void)err; /* TODO */
677 }
678
dump_string(grib_dumper * d,grib_accessor * a,const char * comment)679 static void dump_string(grib_dumper* d, grib_accessor* a, const char* comment)
680 {
681 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
682 char* value = NULL;
683 char* p = NULL;
684 size_t size = 0;
685 grib_context* c = a->context;
686 int r = 0, err = 0;
687 grib_handle* h = grib_handle_of_accessor(a);
688 const char* acc_name = a->name;
689
690 _grib_get_string_length(a, &size);
691 if (size == 0)
692 return;
693
694 if ((a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0 || (a->flags & GRIB_ACCESSOR_FLAG_READ_ONLY) != 0)
695 return;
696
697 value = (char*)grib_context_malloc_clear(c, size);
698 if (!value) {
699 grib_context_log(c, GRIB_LOG_FATAL, "unable to allocate %d bytes", (int)size);
700 return;
701 }
702
703 self->empty = 0;
704
705 err = grib_unpack_string(a, value, &size);
706 p = value;
707 r = compute_bufr_key_rank(h, self->keys, acc_name);
708 if (grib_is_missing_string(a, (unsigned char*)value, size)) {
709 strcpy(value, ""); /* Empty string means MISSING string */
710 }
711
712 while (*p) {
713 if (!isprint(*p))
714 *p = '.';
715 p++;
716 }
717
718 if (self->isLeaf == 0) {
719 depth += 2;
720 if (r != 0)
721 fprintf(self->dumper.out, " codes_set(ibufr, '#%d#%s',", r, acc_name);
722 else
723 fprintf(self->dumper.out, " codes_set(ibufr, '%s',", acc_name);
724 }
725 fprintf(self->dumper.out, "\'%s\')\n", value);
726
727
728 if (self->isLeaf == 0) {
729 char* prefix;
730 int dofree = 0;
731
732 if (r != 0) {
733 prefix = (char*)grib_context_malloc_clear(c, sizeof(char) * (strlen(acc_name) + 10));
734 dofree = 1;
735 sprintf(prefix, "#%d#%s", r, acc_name);
736 }
737 else
738 prefix = (char*)acc_name;
739
740 dump_attributes(d, a, prefix);
741 if (dofree)
742 grib_context_free(c, prefix);
743 depth -= 2;
744 }
745
746 grib_context_free(c, value);
747 (void)err; /* TODO */
748 }
749
dump_bytes(grib_dumper * d,grib_accessor * a,const char * comment)750 static void dump_bytes(grib_dumper* d, grib_accessor* a, const char* comment)
751 {
752 }
753
dump_label(grib_dumper * d,grib_accessor * a,const char * comment)754 static void dump_label(grib_dumper* d, grib_accessor* a, const char* comment)
755 {
756 }
757
_dump_long_array(grib_handle * h,FILE * f,const char * key,const char * print_key)758 static void _dump_long_array(grib_handle* h, FILE* f, const char* key, const char* print_key)
759 {
760 long* val;
761 size_t size = 0, i;
762 int cols = 9, icount = 0;
763
764 if (grib_get_size(h, key, &size) == GRIB_NOT_FOUND)
765 return;
766 if (size == 0)
767 return;
768
769 fprintf(f, " ivalues = (");
770
771 val = (long*)grib_context_malloc_clear(h->context, sizeof(long) * size);
772 grib_get_long_array(h, key, val, &size);
773 for (i = 0; i < size - 1; i++) {
774 if (icount > cols || i == 0) {
775 fprintf(f, " \n ");
776 icount = 0;
777 }
778 fprintf(f, "%ld, ", val[i]);
779 icount++;
780 }
781 if (icount > cols) {
782 fprintf(f, " \n ");
783 }
784 /* Note: In python to make a tuple with one element, you need the trailing comma */
785 if (size > 4)
786 fprintf(f, "%ld ,) # %lu values\n", val[size - 1], (unsigned long)size);
787 else
788 fprintf(f, "%ld ,)\n", val[size - 1]);
789
790 grib_context_free(h->context, val);
791 fprintf(f, " codes_set_array(ibufr, '%s', ivalues)\n", print_key);
792 }
793
dump_section(grib_dumper * d,grib_accessor * a,grib_block_of_accessors * block)794 static void dump_section(grib_dumper* d, grib_accessor* a, grib_block_of_accessors* block)
795 {
796 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
797 if (!grib_inline_strcmp(a->name, "BUFR") ||
798 !grib_inline_strcmp(a->name, "GRIB") ||
799 !grib_inline_strcmp(a->name, "META")) {
800 grib_handle* h = grib_handle_of_accessor(a);
801 depth = 2;
802 self->empty = 1;
803 depth += 2;
804 _dump_long_array(h, self->dumper.out, "dataPresentIndicator", "inputDataPresentIndicator");
805 _dump_long_array(h, self->dumper.out, "delayedDescriptorReplicationFactor", "inputDelayedDescriptorReplicationFactor");
806 _dump_long_array(h, self->dumper.out, "shortDelayedDescriptorReplicationFactor", "inputShortDelayedDescriptorReplicationFactor");
807 _dump_long_array(h, self->dumper.out, "extendedDelayedDescriptorReplicationFactor", "inputExtendedDelayedDescriptorReplicationFactor");
808 _dump_long_array(h, self->dumper.out, "inputOverriddenReferenceValues", "inputOverriddenReferenceValues");
809 grib_dump_accessors_block(d, block);
810 depth -= 2;
811 }
812 else if (!grib_inline_strcmp(a->name, "groupNumber")) {
813 if ((a->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0)
814 return;
815 self->empty = 1;
816 depth += 2;
817 grib_dump_accessors_block(d, block);
818 depth -= 2;
819 }
820 else {
821 grib_dump_accessors_block(d, block);
822 }
823 }
824
dump_attributes(grib_dumper * d,grib_accessor * a,const char * prefix)825 static void dump_attributes(grib_dumper* d, grib_accessor* a, const char* prefix)
826 {
827 int i = 0;
828 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
829 unsigned long flags;
830 while (i < MAX_ACCESSOR_ATTRIBUTES && a->attributes[i]) {
831 self->isAttribute = 1;
832 if ((d->option_flags & GRIB_DUMP_FLAG_ALL_ATTRIBUTES) == 0 && (a->attributes[i]->flags & GRIB_ACCESSOR_FLAG_DUMP) == 0) {
833 i++;
834 continue;
835 }
836 self->isLeaf = a->attributes[i]->attributes[0] == NULL ? 1 : 0;
837 flags = a->attributes[i]->flags;
838 a->attributes[i]->flags |= GRIB_ACCESSOR_FLAG_DUMP;
839 switch (grib_accessor_get_native_type(a->attributes[i])) {
840 case GRIB_TYPE_LONG:
841 dump_long_attribute(d, a->attributes[i], prefix);
842 break;
843 case GRIB_TYPE_DOUBLE:
844 dump_values_attribute(d, a->attributes[i], prefix);
845 break;
846 case GRIB_TYPE_STRING:
847 break;
848 }
849 a->attributes[i]->flags = flags;
850 i++;
851 }
852 self->isLeaf = 0;
853 self->isAttribute = 0;
854 }
855
header(grib_dumper * d,grib_handle * h)856 static void header(grib_dumper* d, grib_handle* h)
857 {
858 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
859 char sampleName[200] = { 0 };
860 long localSectionPresent, edition, bufrHeaderCentre, isSatellite;
861
862 grib_get_long(h, "localSectionPresent", &localSectionPresent);
863 grib_get_long(h, "bufrHeaderCentre", &bufrHeaderCentre);
864 grib_get_long(h, "edition", &edition);
865
866 if (localSectionPresent && bufrHeaderCentre == 98) {
867 grib_get_long(h, "isSatellite", &isSatellite);
868 if (isSatellite)
869 sprintf(sampleName, "BUFR%ld_local_satellite", edition);
870 else
871 sprintf(sampleName, "BUFR%ld_local", edition);
872 }
873 else {
874 sprintf(sampleName, "BUFR%ld", edition);
875 }
876
877 if (d->count < 2) {
878 /* This is the first message being processed */
879 fprintf(self->dumper.out, "# This program was automatically generated with bufr_dump -Epython\n");
880 fprintf(self->dumper.out, "# Using ecCodes version: ");
881 grib_print_api_version(self->dumper.out);
882 fprintf(self->dumper.out, "\n\n");
883 fprintf(self->dumper.out, "from __future__ import print_function\n");
884 fprintf(self->dumper.out, "import traceback\n");
885 fprintf(self->dumper.out, "import sys\n");
886 fprintf(self->dumper.out, "from eccodes import *\n\n\n");
887 fprintf(self->dumper.out, "def bufr_encode():\n");
888 }
889 fprintf(self->dumper.out, " ibufr = codes_bufr_new_from_samples('%s')\n", sampleName);
890 }
891
footer(grib_dumper * d,grib_handle * h)892 static void footer(grib_dumper* d, grib_handle* h)
893 {
894 grib_dumper_bufr_encode_python* self = (grib_dumper_bufr_encode_python*)d;
895 fprintf(self->dumper.out, "\n # Encode the keys back in the data section\n");
896 fprintf(self->dumper.out, " codes_set(ibufr, 'pack', 1)\n\n");
897 if (d->count == 1)
898 fprintf(self->dumper.out, " outfile = open('outfile.bufr', 'wb')\n");
899 else
900 fprintf(self->dumper.out, " outfile = open('outfile.bufr', 'ab')\n");
901
902 fprintf(self->dumper.out, " codes_write(ibufr, outfile)\n");
903 if (d->count == 1)
904 fprintf(self->dumper.out, " print (\"Created output BUFR file 'outfile.bufr'\")\n");
905 /*fprintf(self->dumper.out," codes_close_file(outfile)\n");*/
906 fprintf(self->dumper.out, " codes_release(ibufr)\n");
907 }
908