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 This is used by make_class.pl
18
19 START_CLASS_DEF
20 CLASS = accessor
21 SUPER = grib_accessor_class_abstract_long_vector
22 IMPLEMENTS = pack_string;unpack_string;value_count
23 IMPLEMENTS = pack_long;unpack_long;dump
24 IMPLEMENTS = get_native_type;string_length
25 IMPLEMENTS = init; destroy
26 MEMBERS = const char* p1
27 MEMBERS = const char* p2
28 MEMBERS = const char* timeRangeIndicator
29 MEMBERS = const char *unit
30 MEMBERS = const char *step_unit
31 MEMBERS = const char *stepType
32 MEMBERS = const char *patch_fp_precip
33 MEMBERS = int error_on_units
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 int get_native_type(grib_accessor*);
49 static int pack_long(grib_accessor*, const long* val, size_t* len);
50 static int pack_string(grib_accessor*, const char*, size_t* len);
51 static int unpack_long(grib_accessor*, long* val, size_t* len);
52 static int unpack_string(grib_accessor*, char*, size_t* len);
53 static size_t string_length(grib_accessor*);
54 static int value_count(grib_accessor*, long*);
55 static void destroy(grib_context*, grib_accessor*);
56 static void dump(grib_accessor*, grib_dumper*);
57 static void init(grib_accessor*, const long, grib_arguments*);
58 static void init_class(grib_accessor_class*);
59
60 typedef struct grib_accessor_g1step_range
61 {
62 grib_accessor att;
63 /* Members defined in gen */
64 /* Members defined in abstract_long_vector */
65 long* v;
66 long pack_index;
67 int number_of_elements;
68 /* Members defined in g1step_range */
69 const char* p1;
70 const char* p2;
71 const char* timeRangeIndicator;
72 const char* unit;
73 const char* step_unit;
74 const char* stepType;
75 const char* patch_fp_precip;
76 int error_on_units;
77 } grib_accessor_g1step_range;
78
79 extern grib_accessor_class* grib_accessor_class_abstract_long_vector;
80
81 static grib_accessor_class _grib_accessor_class_g1step_range = {
82 &grib_accessor_class_abstract_long_vector, /* super */
83 "g1step_range", /* name */
84 sizeof(grib_accessor_g1step_range), /* size */
85 0, /* inited */
86 &init_class, /* init_class */
87 &init, /* init */
88 0, /* post_init */
89 &destroy, /* free mem */
90 &dump, /* describes himself */
91 0, /* get length of section */
92 &string_length, /* get length of string */
93 &value_count, /* get number of values */
94 0, /* get number of bytes */
95 0, /* get offset to bytes */
96 &get_native_type, /* get native type */
97 0, /* get sub_section */
98 0, /* grib_pack procedures long */
99 0, /* grib_pack procedures long */
100 &pack_long, /* grib_pack procedures long */
101 &unpack_long, /* grib_unpack procedures long */
102 0, /* grib_pack procedures double */
103 0, /* grib_unpack procedures double */
104 &pack_string, /* grib_pack procedures string */
105 &unpack_string, /* grib_unpack procedures string */
106 0, /* grib_pack array procedures string */
107 0, /* grib_unpack array procedures string */
108 0, /* grib_pack procedures bytes */
109 0, /* grib_unpack procedures bytes */
110 0, /* pack_expression */
111 0, /* notify_change */
112 0, /* update_size */
113 0, /* preferred_size */
114 0, /* resize */
115 0, /* nearest_smaller_value */
116 0, /* next accessor */
117 0, /* compare vs. another accessor */
118 0, /* unpack only ith value */
119 0, /* unpack a subarray */
120 0, /* clear */
121 0, /* clone accessor */
122 };
123
124
125 grib_accessor_class* grib_accessor_class_g1step_range = &_grib_accessor_class_g1step_range;
126
127
init_class(grib_accessor_class * c)128 static void init_class(grib_accessor_class* c)
129 {
130 c->next_offset = (*(c->super))->next_offset;
131 c->byte_count = (*(c->super))->byte_count;
132 c->byte_offset = (*(c->super))->byte_offset;
133 c->sub_section = (*(c->super))->sub_section;
134 c->pack_missing = (*(c->super))->pack_missing;
135 c->is_missing = (*(c->super))->is_missing;
136 c->pack_double = (*(c->super))->pack_double;
137 c->unpack_double = (*(c->super))->unpack_double;
138 c->pack_string_array = (*(c->super))->pack_string_array;
139 c->unpack_string_array = (*(c->super))->unpack_string_array;
140 c->pack_bytes = (*(c->super))->pack_bytes;
141 c->unpack_bytes = (*(c->super))->unpack_bytes;
142 c->pack_expression = (*(c->super))->pack_expression;
143 c->notify_change = (*(c->super))->notify_change;
144 c->update_size = (*(c->super))->update_size;
145 c->preferred_size = (*(c->super))->preferred_size;
146 c->resize = (*(c->super))->resize;
147 c->nearest_smaller_value = (*(c->super))->nearest_smaller_value;
148 c->next = (*(c->super))->next;
149 c->compare = (*(c->super))->compare;
150 c->unpack_double_element = (*(c->super))->unpack_double_element;
151 c->unpack_double_subarray = (*(c->super))->unpack_double_subarray;
152 c->clear = (*(c->super))->clear;
153 c->make_clone = (*(c->super))->make_clone;
154 }
155
156 /* END_CLASS_IMP */
157
init(grib_accessor * a,const long l,grib_arguments * c)158 static void init(grib_accessor* a, const long l, grib_arguments* c)
159 {
160 grib_accessor_g1step_range* self = (grib_accessor_g1step_range*)a;
161 grib_handle* h = grib_handle_of_accessor(a);
162 int n = 0;
163 self->p1 = grib_arguments_get_name(h, c, n++);
164 self->p2 = grib_arguments_get_name(h, c, n++);
165 self->timeRangeIndicator = grib_arguments_get_name(h, c, n++);
166 self->unit = grib_arguments_get_name(h, c, n++);
167 self->step_unit = grib_arguments_get_name(h, c, n++);
168 self->stepType = grib_arguments_get_name(h, c, n++);
169 self->patch_fp_precip = grib_arguments_get_name(h, c, n++);
170 self->error_on_units = 1;
171
172 self->number_of_elements = 2;
173 self->v = (long*)grib_context_malloc_clear(h->context,
174 sizeof(long) * self->number_of_elements);
175 self->pack_index = -1;
176 a->dirty = 1;
177
178 a->length = 0;
179 }
180
dump(grib_accessor * a,grib_dumper * dumper)181 static void dump(grib_accessor* a, grib_dumper* dumper)
182 {
183 grib_dump_string(dumper, a, NULL);
184 }
185
186 static const int u2s1[] = {
187 60, /* (0) minutes */
188 3600, /* (1) hour */
189 86400, /* (2) day */
190 2592000, /* (3) month */
191 -1, /* (4) */
192 -1, /* (5) */
193 -1, /* (6) */
194 -1, /* (7) */
195 -1, /* (8) */
196 -1, /* (9) */
197 10800, /* (10) 3 hours */
198 21600, /* (11) 6 hours */
199 43200, /* (12) 12 hours */
200 900, /* (13) 15 minutes */
201 1800, /* (14) 30 minutes */
202 1 /* (15) seconds */ /* See ECC-316 */
203 };
204
205 static const int units_index[] = {
206 1, 0, 10, 11, 12, 2, 0, 13, 14, 15
207 };
208
209 static const int u2s[] = {
210 60, /* (0) minutes */
211 3600, /* (1) hour */
212 86400, /* (2) day */
213 2592000, /* (3) month */
214 -1, /* (4) */
215 -1, /* (5) */
216 -1, /* (6) */
217 -1, /* (7) */
218 -1, /* (8) */
219 -1, /* (9) */
220 10800, /* (10) 3 hours */
221 21600, /* (11) 6 hours */
222 43200, /* (12) 12 hours */
223 1, /* (13) seconds */
224 900, /* (14) 15 minutes */
225 1800 /* (15) 30 minutes */
226 };
227
228
grib_g1_step_get_steps(grib_accessor * a,long * start,long * theEnd)229 int grib_g1_step_get_steps(grib_accessor* a, long* start, long* theEnd)
230 {
231 grib_accessor_g1step_range* self = (grib_accessor_g1step_range*)a;
232 int err = 0;
233 long p1 = 0, p2 = 0, unit = 0, timeRangeIndicator = 0, timeRangeIndicatorFromStepRange = 0;
234 long step_unit = 1;
235 char stepType[20] = {0,};
236 size_t stepTypeLen = 20;
237 long newstart, newend;
238 int factor = 1;
239 long u2sf, u2sf_step_unit;
240 grib_handle* hand = grib_handle_of_accessor(a);
241
242 if (self->step_unit != NULL)
243 grib_get_long_internal(hand, self->step_unit, &step_unit);
244
245 if (err != GRIB_SUCCESS)
246 return err;
247
248 err = grib_get_long_internal(hand, self->unit, &unit);
249 if (err)
250 return err;
251 if (unit == 254) {
252 unit = 15; /* See ECC-316: WMO says 254 is for 'seconds' but we use 15! */
253 }
254
255 err = grib_get_long_internal(hand, self->p1, &p1);
256 if (err)
257 return err;
258
259 err = grib_get_long_internal(hand, self->p2, &p2);
260 if (err)
261 return err;
262
263 err = grib_get_long_internal(hand, self->timeRangeIndicator, &timeRangeIndicator);
264 if (err)
265 return err;
266
267 /* TODO move to the def file */
268 err = grib_get_long(hand, "timeRangeIndicatorFromStepRange", &timeRangeIndicatorFromStepRange);
269 if (err) return err;
270
271 if (timeRangeIndicatorFromStepRange == 10)
272 timeRangeIndicator = timeRangeIndicatorFromStepRange;
273
274 if (self->stepType) {
275 err = grib_get_string_internal(hand, self->stepType, stepType, &stepTypeLen);
276 if (err)
277 return err;
278 }
279 else
280 sprintf(stepType, "unknown");
281
282 *start = p1;
283 *theEnd = p2;
284
285 if (timeRangeIndicator == 10)
286 *start = *theEnd = (p1 << 8) | (p2 << 0);
287 else if (!strcmp(stepType, "instant"))
288 *start = *theEnd = p1;
289 else if (!strcmp(stepType, "accum") && timeRangeIndicator == 0) {
290 *start = 0;
291 *theEnd = p1;
292 }
293
294 if (u2s1[unit] == u2s[step_unit] || (*start == 0 && *theEnd == 0))
295 return 0;
296
297 newstart = (*start) * u2s1[unit];
298 newend = (*theEnd) * u2s1[unit];
299
300 if (newstart < 0 || newend < 0) {
301 factor = 60;
302 u2sf = u2s1[unit] / factor;
303 if (u2s1[unit] % factor)
304 return GRIB_DECODING_ERROR;
305 newstart = (*start) * u2sf;
306 newend = (*theEnd) * u2sf;
307 u2sf_step_unit = u2s[step_unit] / factor;
308 if (u2s[step_unit] % factor)
309 return GRIB_DECODING_ERROR;
310 }
311 else {
312 u2sf_step_unit = u2s[step_unit];
313 }
314
315 if (newstart % u2sf_step_unit != 0 || newend % u2sf_step_unit != 0) {
316 return GRIB_DECODING_ERROR;
317 }
318 else {
319 *start = newstart / u2sf_step_unit;
320 *theEnd = newend / u2sf_step_unit;
321 }
322
323 return 0;
324 }
325
unpack_string(grib_accessor * a,char * val,size_t * len)326 static int unpack_string(grib_accessor* a, char* val, size_t* len)
327 {
328 grib_accessor_g1step_range* self = (grib_accessor_g1step_range*)a;
329 char buf[100];
330 size_t size = 0;
331 long start = 0, theEnd = 0;
332 long timeRangeIndicator = 0;
333 long unit;
334 int err = 0;
335 char stepType[20] = {0,};
336 size_t stepTypeLen = 20;
337 grib_handle* hand = grib_handle_of_accessor(a);
338
339 if ((err = grib_g1_step_get_steps(a, &start, &theEnd)) != GRIB_SUCCESS) {
340 size_t step_unit_string_len = 10;
341 char step_unit_string[10];
342
343 if (self->step_unit != NULL)
344 grib_get_string(hand, self->step_unit, step_unit_string, &step_unit_string_len);
345 else
346 sprintf(step_unit_string, "h");
347
348 if (self->error_on_units) {
349 grib_get_long_internal(hand, self->unit, &unit);
350 if (unit == 254) {
351 unit = 15; /* See ECC-316 */
352 }
353 grib_set_long_internal(hand, self->step_unit, unit);
354 grib_context_log(a->context, GRIB_LOG_ERROR,
355 "unable to represent the step in %s\n Hint: try changing the step units",
356 step_unit_string);
357 }
358 return err;
359 }
360
361 err = grib_get_long_internal(hand, self->timeRangeIndicator, &timeRangeIndicator);
362 if (err)
363 return err;
364
365 if (self->stepType) {
366 err = grib_get_string_internal(hand, self->stepType, stepType, &stepTypeLen);
367 if (err)
368 return err;
369 }
370 else
371 sprintf(stepType, "unknown");
372
373 /* Patch for old forecast probabilities */
374 if (self->patch_fp_precip) {
375 start += 24;
376 }
377
378 if (strcmp(stepType, "instant") == 0) {
379 sprintf(buf, "%ld", start);
380 }
381 else if ((strcmp(stepType, "avgfc") == 0) ||
382 (strcmp(stepType, "avgua") == 0) ||
383 (strcmp(stepType, "avgia") == 0) ||
384 (strcmp(stepType, "varins") == 0)) {
385 sprintf(buf, "%ld", start);
386 }
387 else if (
388 (strcmp(stepType, "accum") == 0) ||
389 (strcmp(stepType, "avg") == 0) ||
390 (strcmp(stepType, "min") == 0) ||
391 (strcmp(stepType, "max") == 0) ||
392 (strcmp(stepType, "rms") == 0) ||
393 (strcmp(stepType, "diff") == 0) ||
394 (strcmp(stepType, "avgas") == 0) ||
395 (strcmp(stepType, "avgad") == 0) ||
396 (strcmp(stepType, "avgid") == 0) ||
397 (strcmp(stepType, "varas") == 0) ||
398 (strcmp(stepType, "varad") == 0)) {
399 if (start == theEnd) {
400 sprintf(buf, "%ld", theEnd);
401 }
402 else {
403 sprintf(buf, "%ld-%ld", start, theEnd);
404 }
405 }
406 else {
407 grib_context_log(a->context, GRIB_LOG_ERROR, "Unknown stepType=[%s] timeRangeIndicator=[%ld]", stepType, timeRangeIndicator);
408 return GRIB_NOT_IMPLEMENTED;
409 }
410
411 size = strlen(buf) + 1;
412
413 if (*len < size)
414 return GRIB_ARRAY_TOO_SMALL;
415
416 *len = size;
417
418 memcpy(val, buf, size);
419
420 return GRIB_SUCCESS;
421 }
422
grib_g1_step_apply_units(long * start,long * theEnd,long * step_unit,long * P1,long * P2,long * unit,const int max,const int instant)423 int grib_g1_step_apply_units(long* start, long* theEnd, long* step_unit,
424 long* P1, long* P2, long* unit,
425 const int max, const int instant)
426 {
427 int j = 0;
428 long start_sec, end_sec;
429 int index = 0;
430 int max_index = sizeof(units_index) / sizeof(*units_index);
431
432 while (*unit != units_index[index] && index != max_index)
433 index++;
434
435 start_sec = *start * u2s[*step_unit];
436 *P2 = 0;
437
438 if (instant) {
439 *unit = units_index[0];
440 for (j = index; j < max_index; j++) {
441 if (start_sec % u2s1[*unit] == 0 &&
442 (*P1 = start_sec / u2s1[*unit]) <= max)
443 return 0;
444 *unit = units_index[j];
445 }
446 for (j = 0; j < index; j++) {
447 if (start_sec % u2s1[*unit] == 0 &&
448 (*P1 = start_sec / u2s1[*unit]) <= max)
449 return 0;
450 *unit = units_index[j];
451 }
452 }
453 else {
454 end_sec = *theEnd * u2s[*step_unit];
455 *unit = units_index[0];
456 for (j = index; j < max_index; j++) {
457 if (start_sec % u2s1[*unit] == 0 &&
458 end_sec % u2s1[*unit] == 0 &&
459 (*P1 = start_sec / u2s1[*unit]) <= max &&
460 (*P2 = end_sec / u2s1[*unit]) <= max)
461 return 0;
462 *unit = units_index[j];
463 }
464 for (j = 0; j < index; j++) {
465 if (start_sec % u2s1[*unit] == 0 &&
466 end_sec % u2s1[*unit] == 0 &&
467 (*P1 = start_sec / u2s1[*unit]) <= max &&
468 (*P2 = end_sec / u2s1[*unit]) <= max)
469 return 0;
470 *unit = units_index[j];
471 }
472 }
473
474 return GRIB_WRONG_STEP;
475 }
476
pack_string(grib_accessor * a,const char * val,size_t * len)477 static int pack_string(grib_accessor* a, const char* val, size_t* len)
478 {
479 grib_accessor_g1step_range* self = (grib_accessor_g1step_range*)a;
480 grib_handle* h = grib_handle_of_accessor(a);
481 long timeRangeIndicator = 0, P1 = 0, P2 = 0;
482 long start = 0, theEnd = -1, unit = 0, ounit = 0, step_unit = 1;
483 int ret = 0;
484 long end_sec, start_sec;
485 char *p = NULL, *q = NULL;
486 int instant = 0;
487 char stepType[20] = {0,};
488 size_t stepTypeLen = 20;
489
490 if (self->stepType) {
491 ret = grib_get_string_internal(grib_handle_of_accessor(a), self->stepType, stepType, &stepTypeLen);
492 if (ret)
493 return ret;
494 }
495 else
496 sprintf(stepType, "unknown");
497
498 if ((ret = grib_set_long_internal(h, "timeRangeIndicatorFromStepRange", -1)))
499 return ret;
500
501 /* don't change timeRangeIndicator when setting step EXCEPT IF instant*/
502 if ((ret = grib_get_long_internal(h, self->timeRangeIndicator, &timeRangeIndicator)))
503 return ret;
504
505 instant = (strcmp(stepType, "instant") == 0) ? 1 : 0;
506
507 if ((ret = grib_get_long_internal(h, self->unit, &unit)))
508 return ret;
509 if (unit == 254) {
510 unit = 15; /* See ECC-316 */
511 }
512
513 if (self->step_unit != NULL && (ret = grib_get_long_internal(h, self->step_unit, &step_unit)))
514 return ret;
515
516 ounit = unit;
517
518 start = strtol(val, &p, 10);
519 theEnd = start;
520 if (*p != 0)
521 theEnd = strtol(++p, &q, 10);
522
523 if (start == 0 && theEnd == 0) {
524 if ((ret = grib_set_long_internal(h, self->p1, start)) != GRIB_SUCCESS)
525 return ret;
526 ret = grib_set_long_internal(h, self->p2, theEnd);
527 return ret;
528 }
529 end_sec = theEnd * u2s[step_unit];
530 start_sec = start * u2s[step_unit];
531
532 if ((end_sec > 918000 || start_sec > 918000) &&
533 h->context->gribex_mode_on && instant) {
534 timeRangeIndicator = 10;
535 if ((ret = grib_set_long_internal(h, self->timeRangeIndicator, 10)))
536 return ret;
537 /* TODO move to the def file*/
538 if ((ret = grib_set_long_internal(h, "timeRangeIndicatorFromStepRange", 10)))
539 return ret;
540 }
541
542 if (timeRangeIndicator == 10) {
543 /*
544 * timeRangeIndicator = 10 means 'P1 occupies octets 19 and 20' i.e. 16 bits
545 */
546 long off = 0;
547 grib_accessor* p1_accessor = NULL;
548 if (theEnd != start && !h->context->gribex_mode_on) {
549 if (h->context->gribex_mode_on == 0) {
550 grib_context_log(h->context, GRIB_LOG_ERROR,
551 "Unable to set %s: end must be equal to start when timeRangeIndicator=10",
552 a->name);
553 return GRIB_WRONG_STEP;
554 }
555 else
556 start = theEnd;
557 }
558 if ((ret = grib_g1_step_apply_units(&start, &theEnd, &step_unit, &P1, &P2, &unit, 65535, instant)) != GRIB_SUCCESS) {
559 grib_context_log(h->context, GRIB_LOG_ERROR, "unable to find units to set %s=%s", a->name, val);
560 return ret;
561 }
562
563 p1_accessor = grib_find_accessor(grib_handle_of_accessor(a), self->p1);
564 if (p1_accessor == NULL) {
565 grib_context_log(h->context, GRIB_LOG_ERROR, "unable to find accessor %s", self->p1);
566 return GRIB_NOT_FOUND;
567 }
568 off = p1_accessor->offset * 8;
569 /* Note: here we assume the key P2 is one octet and immediately follows P1. Hence 16 bits */
570 if (h->context->debug)
571 fprintf(stderr, "ECCODES DEBUG grib_set_long %s=%ld (as two octets)\n", p1_accessor->name, P1);
572 ret = grib_encode_unsigned_long(grib_handle_of_accessor(a)->buffer->data, P1, &off, 16);
573 if (ret != 0)
574 return ret;
575
576 if (ounit != unit)
577 ret = grib_set_long_internal(h, self->unit, unit);
578
579 return ret;
580 }
581
582 if ((ret = grib_g1_step_apply_units(&start, &theEnd, &step_unit, &P1, &P2, &unit, 255, instant)) != GRIB_SUCCESS) {
583 if (instant || h->context->gribex_mode_on) {
584 long off = 0;
585 grib_accessor* p1_accessor = NULL;
586 if ((ret = grib_set_long_internal(h, self->timeRangeIndicator, 10)))
587 return ret;
588 /* TODO move to the def file*/
589 if ((ret = grib_set_long_internal(h, "timeRangeIndicatorFromStepRange", 10)))
590 return ret;
591 if (theEnd != start && !h->context->gribex_mode_on) {
592 grib_context_log(h->context, GRIB_LOG_ERROR,
593 "Unable to set %s: end must be equal to start when timeRangeIndicator=10",
594 a->name);
595 return GRIB_WRONG_STEP;
596 }
597 else
598 start = theEnd;
599
600 if ((ret = grib_g1_step_apply_units(&start, &theEnd, &step_unit, &P1, &P2, &unit, 65535, instant)) != GRIB_SUCCESS) {
601 grib_context_log(h->context, GRIB_LOG_ERROR, "unable to find units to set %s=%s", a->name, val);
602 return ret;
603 }
604
605 p1_accessor = grib_find_accessor(grib_handle_of_accessor(a), self->p1);
606 if (p1_accessor == NULL) {
607 grib_context_log(h->context, GRIB_LOG_ERROR, "unable to find accessor %s", self->p1);
608 return GRIB_NOT_FOUND;
609 }
610 off = p1_accessor->offset * 8;
611 /* Note: case for timeRangeIndicator of 10
612 * We assume the key P2 is one octet and immediately follows P1. Hence 16 bits
613 */
614 if (h->context->debug)
615 fprintf(stderr, "ECCODES DEBUG grib_set_long %s=%ld (as two octets)\n", p1_accessor->name, P1);
616 ret = grib_encode_unsigned_long(grib_handle_of_accessor(a)->buffer->data, P1, &off, 16);
617 if (ret != 0)
618 return ret;
619
620 if (ounit != unit)
621 ret = grib_set_long_internal(h, self->unit, unit);
622 }
623
624 return ret;
625 }
626
627 if (ounit != unit)
628 if ((ret = grib_set_long_internal(h, self->unit, unit)) != GRIB_SUCCESS)
629 return ret;
630
631 if ((ret = grib_set_long_internal(h, self->p1, P1)) != GRIB_SUCCESS)
632 return ret;
633 if ((ret = grib_set_long_internal(h, self->p2, P2)) != GRIB_SUCCESS)
634 return ret;
635
636 self->v[0] = start;
637 self->v[1] = theEnd;
638 a->dirty = 0;
639
640 return 0;
641 }
642
value_count(grib_accessor * a,long * count)643 static int value_count(grib_accessor* a, long* count)
644 {
645 *count = 1;
646 return 0;
647 }
648
string_length(grib_accessor * a)649 static size_t string_length(grib_accessor* a)
650 {
651 return 255;
652 }
653
pack_long(grib_accessor * a,const long * val,size_t * len)654 static int pack_long(grib_accessor* a, const long* val, size_t* len)
655 {
656 char buff[256];
657 size_t bufflen = 100;
658 char sval[100] = { 0 };
659 char* p = sval;
660 size_t svallen = 100;
661 grib_accessor_g1step_range* self = (grib_accessor_g1step_range*)a;
662 char stepType[20] = {0,};
663 size_t stepTypeLen = 20;
664 long step_unit = 0;
665 int err = 0;
666
667 if (self->stepType) {
668 err = grib_get_string_internal(grib_handle_of_accessor(a), self->stepType, stepType, &stepTypeLen);
669 if (err)
670 return err;
671 }
672 else
673 sprintf(stepType, "unknown");
674
675 if (self->step_unit != NULL && (err = grib_get_long_internal(grib_handle_of_accessor(a), self->step_unit, &step_unit)))
676 return err;
677
678 switch (self->pack_index) {
679 case -1:
680 self->pack_index = -1;
681 sprintf(buff, "%ld", *val);
682 return pack_string(a, buff, &bufflen);
683 case 0:
684 self->pack_index = -1;
685 self->error_on_units = 0;
686 unpack_string(a, sval, &svallen);
687 self->error_on_units = 1;
688 while (*p != '-' && *p != '\0')
689 p++;
690 if (*p == '-') {
691 sprintf(buff, "%ld-%s", *val, ++p);
692 }
693 else {
694 if (strcmp(stepType, "instant") && strcmp(stepType, "avgd")) {
695 sprintf(buff, "%ld-%s", *val, sval);
696 }
697 else {
698 sprintf(buff, "%ld", *val);
699 }
700 }
701 return pack_string(a, buff, &bufflen);
702 case 1:
703 self->pack_index = -1;
704 self->error_on_units = 0;
705 unpack_string(a, sval, &svallen);
706 self->error_on_units = 1;
707 while (*p != '-' && *p != '\0')
708 p++;
709 if (*p == '-') {
710 *p = '\0';
711 sprintf(buff, "%s-%ld", sval, *val);
712 }
713 else {
714 if (strcmp(stepType, "instant") && strcmp(stepType, "avgd")) {
715 sprintf(buff, "%s-%ld", sval, *val);
716 }
717 else {
718 sprintf(buff, "%ld", *val);
719 }
720 }
721 return pack_string(a, buff, &bufflen);
722 default:
723 Assert(self->pack_index < 2);
724 break;
725 }
726
727 return GRIB_INTERNAL_ERROR;
728 }
729
unpack_long(grib_accessor * a,long * val,size_t * len)730 static int unpack_long(grib_accessor* a, long* val, size_t* len)
731 {
732 grib_accessor_g1step_range* self = (grib_accessor_g1step_range*)a;
733 char buff[100];
734 size_t bufflen = 100;
735 long start, theEnd;
736 char* p = buff;
737 char* q = NULL;
738 int err = 0;
739
740 /*TODO implement dirty*/
741 if ((err = unpack_string(a, buff, &bufflen)) != GRIB_SUCCESS)
742 return err;
743
744 start = strtol(buff, &p, 10);
745 theEnd = start;
746 if (*p != 0)
747 theEnd = strtol(++p, &q, 10);
748
749 if (self->pack_index == 1)
750 *val = start;
751 else
752 *val = theEnd;
753
754 self->v[0] = start;
755 self->v[1] = theEnd;
756 a->dirty = 0;
757
758 return 0;
759 }
760
get_native_type(grib_accessor * a)761 static int get_native_type(grib_accessor* a)
762 {
763 return GRIB_TYPE_STRING;
764 }
765
destroy(grib_context * c,grib_accessor * a)766 static void destroy(grib_context* c, grib_accessor* a)
767 {
768 grib_accessor_g1step_range* self = (grib_accessor_g1step_range*)a;
769 grib_context_free(c, self->v);
770 }
771