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