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 /*
13    This is used by make_class.pl
14 
15    START_CLASS_DEF
16    CLASS      = accessor
17    SUPER      = grib_accessor_class_bytes
18 
19    IMPLEMENTS = next_offset
20    IMPLEMENTS = unpack_double;unpack_double_element
21    IMPLEMENTS = unpack_long
22    IMPLEMENTS = unpack_string
23    IMPLEMENTS = init;dump;update_size
24    MEMBERS=const char* tableReference
25    MEMBERS=const char* missing_value
26    MEMBERS=const char* offsetbsec
27    MEMBERS=const char* sLength
28    END_CLASS_DEF
29 
30  */
31 
32 /* START_CLASS_IMP */
33 
34 /*
35 
36 Don't edit anything between START_CLASS_IMP and END_CLASS_IMP
37 Instead edit values between START_CLASS_DEF and END_CLASS_DEF
38 or edit "accessor.class" and rerun ./make_class.pl
39 
40 */
41 
42 static int unpack_double(grib_accessor*, double* val, size_t* len);
43 static int unpack_long(grib_accessor*, long* val, size_t* len);
44 static int unpack_string(grib_accessor*, char*, size_t* len);
45 static long next_offset(grib_accessor*);
46 static void dump(grib_accessor*, grib_dumper*);
47 static void init(grib_accessor*, const long, grib_arguments*);
48 static void init_class(grib_accessor_class*);
49 static void update_size(grib_accessor*, size_t);
50 static int unpack_double_element(grib_accessor*, size_t i, double* val);
51 
52 typedef struct grib_accessor_bitmap
53 {
54     grib_accessor att;
55     /* Members defined in gen */
56     /* Members defined in bytes */
57     /* Members defined in bitmap */
58     const char* tableReference;
59     const char* missing_value;
60     const char* offsetbsec;
61     const char* sLength;
62 } grib_accessor_bitmap;
63 
64 extern grib_accessor_class* grib_accessor_class_bytes;
65 
66 static grib_accessor_class _grib_accessor_class_bitmap = {
67     &grib_accessor_class_bytes,   /* super                     */
68     "bitmap",                     /* name                      */
69     sizeof(grib_accessor_bitmap), /* size                      */
70     0,                            /* inited */
71     &init_class,                  /* init_class */
72     &init,                        /* init                      */
73     0,                            /* post_init                      */
74     0,                            /* free mem                       */
75     &dump,                        /* describes himself         */
76     &next_offset,                 /* get length of section     */
77     0,                            /* get length of string      */
78     0,                            /* get number of values      */
79     0,                            /* get number of bytes      */
80     0,                            /* get offset to bytes           */
81     0,                            /* get native type               */
82     0,                            /* get sub_section                */
83     0,                            /* grib_pack procedures long      */
84     0,                            /* grib_pack procedures long      */
85     0,                            /* grib_pack procedures long      */
86     &unpack_long,                 /* grib_unpack procedures long    */
87     0,                            /* grib_pack procedures double    */
88     &unpack_double,               /* grib_unpack procedures double  */
89     0,                            /* grib_pack procedures string    */
90     &unpack_string,               /* grib_unpack procedures string  */
91     0,                            /* grib_pack array procedures string    */
92     0,                            /* grib_unpack array procedures string  */
93     0,                            /* grib_pack procedures bytes     */
94     0,                            /* grib_unpack procedures bytes   */
95     0,                            /* pack_expression */
96     0,                            /* notify_change   */
97     &update_size,                 /* update_size   */
98     0,                            /* preferred_size   */
99     0,                            /* resize   */
100     0,                            /* nearest_smaller_value */
101     0,                            /* next accessor    */
102     0,                            /* compare vs. another accessor   */
103     &unpack_double_element,       /* unpack only ith value          */
104     0,                            /* unpack a subarray         */
105     0,                            /* clear          */
106     0,                            /* clone accessor          */
107 };
108 
109 
110 grib_accessor_class* grib_accessor_class_bitmap = &_grib_accessor_class_bitmap;
111 
112 
init_class(grib_accessor_class * c)113 static void init_class(grib_accessor_class* c)
114 {
115     c->string_length          = (*(c->super))->string_length;
116     c->value_count            = (*(c->super))->value_count;
117     c->byte_count             = (*(c->super))->byte_count;
118     c->byte_offset            = (*(c->super))->byte_offset;
119     c->get_native_type        = (*(c->super))->get_native_type;
120     c->sub_section            = (*(c->super))->sub_section;
121     c->pack_missing           = (*(c->super))->pack_missing;
122     c->is_missing             = (*(c->super))->is_missing;
123     c->pack_long              = (*(c->super))->pack_long;
124     c->pack_double            = (*(c->super))->pack_double;
125     c->pack_string            = (*(c->super))->pack_string;
126     c->pack_string_array      = (*(c->super))->pack_string_array;
127     c->unpack_string_array    = (*(c->super))->unpack_string_array;
128     c->pack_bytes             = (*(c->super))->pack_bytes;
129     c->unpack_bytes           = (*(c->super))->unpack_bytes;
130     c->pack_expression        = (*(c->super))->pack_expression;
131     c->notify_change          = (*(c->super))->notify_change;
132     c->preferred_size         = (*(c->super))->preferred_size;
133     c->resize                 = (*(c->super))->resize;
134     c->nearest_smaller_value  = (*(c->super))->nearest_smaller_value;
135     c->next                   = (*(c->super))->next;
136     c->compare                = (*(c->super))->compare;
137     c->unpack_double_subarray = (*(c->super))->unpack_double_subarray;
138     c->clear                  = (*(c->super))->clear;
139     c->make_clone             = (*(c->super))->make_clone;
140 }
141 
142 /* END_CLASS_IMP */
143 
144 
compute_size(grib_accessor * a)145 static void compute_size(grib_accessor* a)
146 {
147     long slen         = 0;
148     long off          = 0;
149     grib_handle* hand = grib_handle_of_accessor(a);
150 
151     grib_accessor_bitmap* self = (grib_accessor_bitmap*)a;
152     grib_get_long_internal(hand, self->offsetbsec, &off);
153     grib_get_long_internal(hand, self->sLength, &slen);
154 
155     if (slen == 0) {
156         grib_accessor* seclen;
157         size_t size;
158         /* Assume reparsing */
159         Assert(hand->loader != 0);
160         if (hand->loader != 0) {
161             seclen = grib_find_accessor(hand, self->sLength);
162             Assert(seclen);
163             grib_get_block_length(seclen->parent, &size);
164             slen = size;
165         }
166     }
167 
168 #if 0
169     printf("compute_size off=%ld slen=%ld a->offset=%ld\n",
170             (long)off,(long)slen,(long)a->offset);
171 #endif
172 
173     a->length = off + (slen - a->offset);
174 
175     if (a->length < 0) {
176         /* Assume reparsing */
177         /*Assert(hand->loader != 0);*/
178         a->length = 0;
179     }
180 
181     Assert(a->length >= 0);
182 }
183 
init(grib_accessor * a,const long len,grib_arguments * arg)184 static void init(grib_accessor* a, const long len, grib_arguments* arg)
185 {
186     grib_accessor_bitmap* self = (grib_accessor_bitmap*)a;
187     grib_handle* hand          = grib_handle_of_accessor(a);
188     int n                      = 0;
189 
190     self->tableReference = grib_arguments_get_name(hand, arg, n++);
191     self->missing_value  = grib_arguments_get_name(hand, arg, n++);
192     self->offsetbsec     = grib_arguments_get_name(hand, arg, n++);
193     self->sLength        = grib_arguments_get_name(hand, arg, n++);
194 
195     compute_size(a);
196 }
197 
next_offset(grib_accessor * a)198 static long next_offset(grib_accessor* a)
199 {
200     return grib_byte_offset(a) + grib_byte_count(a);
201 }
202 
dump(grib_accessor * a,grib_dumper * dumper)203 static void dump(grib_accessor* a, grib_dumper* dumper)
204 {
205     long len = 0;
206     char label[1024];
207 
208     grib_value_count(a, &len);
209 
210     sprintf(label, "Bitmap of %ld values", len);
211     grib_dump_bytes(dumper, a, label);
212 }
213 
unpack_long(grib_accessor * a,long * val,size_t * len)214 static int unpack_long(grib_accessor* a, long* val, size_t* len)
215 {
216     long pos          = a->offset * 8;
217     long tlen         = 0;
218     long i            = 0;
219     int err           = 0;
220     grib_handle* hand = grib_handle_of_accessor(a);
221 
222     err = grib_value_count(a, &tlen);
223     if (err)
224         return err;
225 
226     if (*len < tlen) {
227         grib_context_log(a->context, GRIB_LOG_ERROR, "Wrong size for %s it contains %d values ", a->name, tlen);
228         *len = 0;
229         return GRIB_ARRAY_TOO_SMALL;
230     }
231 
232     for (i = 0; i < tlen; i++) {
233         val[i] = (long)grib_decode_unsigned_long(hand->buffer->data, &pos, 1);
234     }
235     *len = tlen;
236     return GRIB_SUCCESS;
237 }
238 
unpack_double(grib_accessor * a,double * val,size_t * len)239 static int unpack_double(grib_accessor* a, double* val, size_t* len)
240 {
241     long pos = a->offset * 8;
242     long tlen;
243     long i;
244     int err           = 0;
245     grib_handle* hand = grib_handle_of_accessor(a);
246 
247     err = grib_value_count(a, &tlen);
248     if (err)
249         return err;
250 
251     if (*len < tlen) {
252         grib_context_log(a->context, GRIB_LOG_ERROR, "Wrong size for %s it contains %d values ", a->name, tlen);
253         *len = 0;
254         return GRIB_ARRAY_TOO_SMALL;
255     }
256 
257     for (i = 0; i < tlen; i++) {
258         val[i] = (double)grib_decode_unsigned_long(hand->buffer->data, &pos, 1);
259     }
260     *len = tlen;
261     return GRIB_SUCCESS;
262 }
263 
unpack_double_element(grib_accessor * a,size_t idx,double * val)264 static int unpack_double_element(grib_accessor* a, size_t idx, double* val)
265 {
266     long pos = a->offset * 8;
267 
268     pos += idx;
269     *val = (double)grib_decode_unsigned_long(grib_handle_of_accessor(a)->buffer->data, &pos, 1);
270 
271     return GRIB_SUCCESS;
272 }
273 
update_size(grib_accessor * a,size_t s)274 static void update_size(grib_accessor* a, size_t s)
275 {
276     a->length = s;
277 }
278 
unpack_string(grib_accessor * a,char * val,size_t * len)279 static int unpack_string(grib_accessor* a, char* val, size_t* len)
280 {
281     int i             = 0;
282     grib_handle* hand = grib_handle_of_accessor(a);
283 
284     if (len[0] < (a->length)) {
285         grib_context_log(a->context, GRIB_LOG_ERROR, "unpack_string: Wrong size (%d) for %s it contains %d values ", len[0], a->name, a->length);
286         len[0] = 0;
287         return GRIB_ARRAY_TOO_SMALL;
288     }
289 
290     for (i = 0; i < a->length; i++)
291         val[i] = hand->buffer->data[a->offset + i];
292 
293     len[0] = a->length;
294 
295     return GRIB_SUCCESS;
296 }
297