1 /*
2 * Copyright 2005-2018 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
13 /*
14 This is used by make_class.pl
15
16 START_CLASS_DEF
17 CLASS = accessor
18 SUPER = grib_accessor_class_data_simple_packing
19 IMPLEMENTS = init
20 IMPLEMENTS = pack_double
21 IMPLEMENTS = value_count
22 MEMBERS=const char* half_byte
23 MEMBERS=const char* packingType
24 MEMBERS=const char* ieee_packing
25 MEMBERS=const char* precision
26 END_CLASS_DEF
27
28 */
29
30 /* START_CLASS_IMP */
31
32 /*
33
34 Don't edit anything between START_CLASS_IMP and END_CLASS_IMP
35 Instead edit values between START_CLASS_DEF and END_CLASS_DEF
36 or edit "accessor.class" and rerun ./make_class.pl
37
38 */
39
40 static int pack_double(grib_accessor*, const double* val,size_t *len);
41 static int value_count(grib_accessor*,long*);
42 static void init(grib_accessor*,const long, grib_arguments* );
43 static void init_class(grib_accessor_class*);
44
45 typedef struct grib_accessor_data_g1simple_packing {
46 grib_accessor att;
47 /* Members defined in gen */
48 /* Members defined in values */
49 int carg;
50 const char* seclen;
51 const char* offsetdata;
52 const char* offsetsection;
53 int dirty;
54 /* Members defined in data_simple_packing */
55 int edition;
56 const char* units_factor;
57 const char* units_bias;
58 const char* changing_precision;
59 const char* number_of_values;
60 const char* bits_per_value;
61 const char* reference_value;
62 const char* binary_scale_factor;
63 const char* decimal_scale_factor;
64 /* Members defined in data_g1simple_packing */
65 const char* half_byte;
66 const char* packingType;
67 const char* ieee_packing;
68 const char* precision;
69 } grib_accessor_data_g1simple_packing;
70
71 extern grib_accessor_class* grib_accessor_class_data_simple_packing;
72
73 static grib_accessor_class _grib_accessor_class_data_g1simple_packing = {
74 &grib_accessor_class_data_simple_packing, /* super */
75 "data_g1simple_packing", /* name */
76 sizeof(grib_accessor_data_g1simple_packing), /* size */
77 0, /* inited */
78 &init_class, /* init_class */
79 &init, /* init */
80 0, /* post_init */
81 0, /* free mem */
82 0, /* describes himself */
83 0, /* get length of section */
84 0, /* get length of string */
85 &value_count, /* get number of values */
86 0, /* get number of bytes */
87 0, /* get offset to bytes */
88 0, /* get native type */
89 0, /* get sub_section */
90 0, /* grib_pack procedures long */
91 0, /* grib_pack procedures long */
92 0, /* grib_pack procedures long */
93 0, /* grib_unpack procedures long */
94 &pack_double, /* grib_pack procedures double */
95 0, /* grib_unpack procedures double */
96 0, /* grib_pack procedures string */
97 0, /* grib_unpack procedures string */
98 0, /* grib_pack procedures bytes */
99 0, /* grib_unpack procedures bytes */
100 0, /* pack_expression */
101 0, /* notify_change */
102 0, /* update_size */
103 0, /* preferred_size */
104 0, /* resize */
105 0, /* nearest_smaller_value */
106 0, /* next accessor */
107 0, /* compare vs. another accessor */
108 0, /* unpack only ith value */
109 0, /* unpack a subarray */
110 0, /* clear */
111 };
112
113
114 grib_accessor_class* grib_accessor_class_data_g1simple_packing = &_grib_accessor_class_data_g1simple_packing;
115
116
init_class(grib_accessor_class * c)117 static void init_class(grib_accessor_class* c)
118 {
119 c->dump = (*(c->super))->dump;
120 c->next_offset = (*(c->super))->next_offset;
121 c->string_length = (*(c->super))->string_length;
122 c->byte_count = (*(c->super))->byte_count;
123 c->byte_offset = (*(c->super))->byte_offset;
124 c->get_native_type = (*(c->super))->get_native_type;
125 c->sub_section = (*(c->super))->sub_section;
126 c->pack_missing = (*(c->super))->pack_missing;
127 c->is_missing = (*(c->super))->is_missing;
128 c->pack_long = (*(c->super))->pack_long;
129 c->unpack_long = (*(c->super))->unpack_long;
130 c->unpack_double = (*(c->super))->unpack_double;
131 c->pack_string = (*(c->super))->pack_string;
132 c->unpack_string = (*(c->super))->unpack_string;
133 c->pack_bytes = (*(c->super))->pack_bytes;
134 c->unpack_bytes = (*(c->super))->unpack_bytes;
135 c->pack_expression = (*(c->super))->pack_expression;
136 c->notify_change = (*(c->super))->notify_change;
137 c->update_size = (*(c->super))->update_size;
138 c->preferred_size = (*(c->super))->preferred_size;
139 c->resize = (*(c->super))->resize;
140 c->nearest_smaller_value = (*(c->super))->nearest_smaller_value;
141 c->next = (*(c->super))->next;
142 c->compare = (*(c->super))->compare;
143 c->unpack_double_element = (*(c->super))->unpack_double_element;
144 c->unpack_double_subarray = (*(c->super))->unpack_double_subarray;
145 c->clear = (*(c->super))->clear;
146 }
147
148 /* END_CLASS_IMP */
149
init(grib_accessor * a,const long v,grib_arguments * args)150 static void init(grib_accessor* a,const long v, grib_arguments* args)
151 {
152 grib_accessor_data_g1simple_packing *self =(grib_accessor_data_g1simple_packing*)a;
153
154 self->half_byte = grib_arguments_get_name(a->parent->h,args,self->carg++);
155 self->packingType = grib_arguments_get_name(a->parent->h,args,self->carg++);
156 self->ieee_packing = grib_arguments_get_name(a->parent->h,args,self->carg++);
157 self->precision = grib_arguments_get_name(a->parent->h,args,self->carg++);
158 self->edition=1;
159 a->flags |= GRIB_ACCESSOR_FLAG_DATA;
160
161 }
162
value_count(grib_accessor * a,long * number_of_values)163 static int value_count(grib_accessor* a,long* number_of_values)
164 {
165 grib_accessor_data_g1simple_packing *self =(grib_accessor_data_g1simple_packing*)a;
166 *number_of_values=0;
167
168 /* Special case for when values are cleared */
169 /*if(a->length == 0)
170 return 0;*/
171
172 return grib_get_long_internal(a->parent->h,self->number_of_values,number_of_values);
173 }
174
pack_double(grib_accessor * a,const double * cval,size_t * len)175 static int pack_double(grib_accessor* a, const double* cval, size_t *len)
176 {
177 grib_accessor_data_g1simple_packing* self = (grib_accessor_data_g1simple_packing*)a;
178 grib_accessor_class* super = *(a->cclass->super);
179
180 size_t n_vals = *len;
181 long half_byte = 0;
182 int ret = 0;
183 long offsetdata = 0;
184 long offsetsection = 0;
185 double reference_value = 0;
186 long binary_scale_factor = 0;
187 long bits_per_value = 0;
188 long decimal_scale_factor = 0;
189 double decimal = 1;
190 size_t buflen = 0;
191 unsigned char* buf = NULL;
192 unsigned char* encoded = NULL;
193 double divisor = 1;
194 int i;
195 long off = 0;
196 grib_context* c=a->parent->h->context;
197 grib_handle* h=a->parent->h;
198 char* ieee_packing_s=NULL;
199 char* packingType_s=NULL;
200 char* precision_s=NULL;
201 double units_factor=1.0;
202 double units_bias=0.0;
203 double* val=(double*)cval;
204 double missingValue=9999.0;
205 long constantFieldHalfByte=0;
206 int err=0;
207
208 if(*len != 0) {
209 if(self->units_factor &&
210 (grib_get_double_internal(a->parent->h,self->units_factor,&units_factor)== GRIB_SUCCESS)) {
211 grib_set_double_internal(a->parent->h,self->units_factor,1.0);
212 }
213
214 if(self->units_bias &&
215 (grib_get_double_internal(a->parent->h,self->units_bias,&units_bias)== GRIB_SUCCESS)) {
216 grib_set_double_internal(a->parent->h,self->units_bias,0.0);
217 }
218
219 if (units_factor != 1.0) {
220 if (units_bias != 0.0)
221 for (i=0;i<n_vals;i++) val[i]=val[i]*units_factor+units_bias;
222 else
223 for (i=0;i<n_vals;i++) val[i]*=units_factor;
224 } else if (units_bias != 0.0)
225 for (i=0;i<n_vals;i++) val[i]+=units_bias;
226
227 if (c->ieee_packing && self->ieee_packing) {
228 long precision=c->ieee_packing==32 ? 1 : 2;
229 size_t lenstr=strlen(self->ieee_packing);
230
231 packingType_s=grib_context_strdup(c,self->packingType);
232 ieee_packing_s=grib_context_strdup(c,self->ieee_packing);
233 precision_s=grib_context_strdup(c,self->precision);
234
235 grib_set_string(h,packingType_s,ieee_packing_s,&lenstr);
236 grib_set_long(h,precision_s,precision);
237
238 grib_context_free(c,packingType_s);
239 grib_context_free(c,ieee_packing_s);
240 grib_context_free(c,precision_s);
241 return grib_set_double_array(h,"values",val,*len);
242 }
243 }
244
245 ret = super->pack_double(a,val,len);
246 switch (ret) {
247 case GRIB_CONSTANT_FIELD:
248 ret=grib_get_long(a->parent->h,"constantFieldHalfByte",&constantFieldHalfByte);
249 if (ret) constantFieldHalfByte=0;
250 if((ret = grib_set_long_internal(a->parent->h,self->half_byte, constantFieldHalfByte))
251 != GRIB_SUCCESS)
252 return ret;
253 grib_buffer_replace(a, NULL, 0,1,1);
254 return GRIB_SUCCESS;
255 break;
256 case GRIB_NO_VALUES:
257 ret=grib_get_long(a->parent->h,"constantFieldHalfByte",&constantFieldHalfByte);
258 if (ret) constantFieldHalfByte=0;
259 /* TODO move to def file */
260 grib_get_double(a->parent->h,"missingValue", &missingValue);
261 if((err = grib_set_double_internal(a->parent->h,self->reference_value, missingValue)) !=
262 GRIB_SUCCESS)
263 return err;
264 if((ret = grib_set_long_internal(a->parent->h,self->binary_scale_factor, binary_scale_factor))
265 != GRIB_SUCCESS)
266 return ret;
267 if((ret = grib_set_long_internal(a->parent->h,self->half_byte, constantFieldHalfByte))
268 != GRIB_SUCCESS)
269 return ret;
270 grib_buffer_replace(a, NULL, 0,1,1);
271 return GRIB_SUCCESS;
272 break;
273 case GRIB_INVALID_BPV:
274 grib_context_log(a->parent->h->context,GRIB_LOG_ERROR,"unable to compute packing parameters\n");
275 return ret;
276 case GRIB_SUCCESS:
277 break;
278 default:
279 grib_context_log(a->parent->h->context,GRIB_LOG_FATAL,"unable to compute packing parameters\n");
280 return ret;
281 }
282
283 if((ret = grib_get_double_internal(a->parent->h,self->reference_value, &reference_value))
284 != GRIB_SUCCESS)
285 return ret;
286
287 if((ret = grib_get_long_internal(a->parent->h,self->binary_scale_factor, &binary_scale_factor))
288 != GRIB_SUCCESS)
289 return ret;
290
291 if((ret = grib_get_long_internal(a->parent->h,self->bits_per_value,&bits_per_value)) !=
292 GRIB_SUCCESS)
293 return ret;
294
295 if((ret = grib_get_long_internal(a->parent->h,self->decimal_scale_factor, &decimal_scale_factor))
296 != GRIB_SUCCESS)
297 return ret;
298
299 if((ret = grib_get_long_internal(a->parent->h,self->offsetdata,&offsetdata)) != GRIB_SUCCESS)
300 return ret;
301
302 if((ret = grib_get_long_internal(a->parent->h,self->offsetsection,&offsetsection)) != GRIB_SUCCESS)
303 return ret;
304
305 decimal = grib_power(decimal_scale_factor,10) ;
306 divisor = grib_power(-binary_scale_factor,2);
307
308 buflen = (((bits_per_value*n_vals)+7)/8)*sizeof(unsigned char);
309 if((buflen + (offsetdata-offsetsection)) %2) {
310 buflen++;
311 /*
312 a->length++;
313 a->parent->h->buffer->ulength++;
314 */
315 }
316 half_byte = (buflen*8)-((*len)*bits_per_value);
317 grib_context_log(a->parent->h->context,GRIB_LOG_DEBUG,
318 "HALF byte: buflen=%d bits_per_value=%ld len=%d half_byte=%ld\n",
319 buflen,bits_per_value,*len,half_byte);
320
321 Assert(half_byte <= 0x0f);
322
323 if((ret = grib_set_long_internal(a->parent->h,self->half_byte, half_byte))
324 != GRIB_SUCCESS)
325 return ret;
326
327 buf = (unsigned char*)grib_context_buffer_malloc_clear(a->parent->h->context,buflen);
328 encoded = buf;
329
330 grib_encode_double_array(n_vals,val,bits_per_value,reference_value,decimal,divisor,encoded,&off);
331
332 grib_context_log(a->parent->h->context, GRIB_LOG_DEBUG,
333 "grib_accessor_data_g1simple_packing : pack_double : packing %s, %d values", a->name, n_vals);
334
335 grib_buffer_replace(a, buf, buflen,1,1);
336
337 grib_context_buffer_free(a->parent->h->context,buf);
338
339 return GRIB_SUCCESS;
340 }
341