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_gen
18    IMPLEMENTS = get_native_type;init;update_size; pack_bytes
19    IMPLEMENTS = compare;unpack_bytes;byte_count;value_count
20    MEMBERS    = const char* totalLength
21    MEMBERS    = const char* sectionLength
22    MEMBERS    = long relativeOffset
23    END_CLASS_DEF
24 
25  */
26 
27 /* START_CLASS_IMP */
28 
29 /*
30 
31 Don't edit anything between START_CLASS_IMP and END_CLASS_IMP
32 Instead edit values between START_CLASS_DEF and END_CLASS_DEF
33 or edit "accessor.class" and rerun ./make_class.pl
34 
35 */
36 
37 static int get_native_type(grib_accessor*);
38 static int pack_bytes(grib_accessor*, const unsigned char*, size_t* len);
39 static int unpack_bytes(grib_accessor*, unsigned char*, size_t* len);
40 static long byte_count(grib_accessor*);
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 static void update_size(grib_accessor*, size_t);
45 static int compare(grib_accessor*, grib_accessor*);
46 
47 typedef struct grib_accessor_raw
48 {
49     grib_accessor att;
50     /* Members defined in gen */
51     /* Members defined in raw */
52     const char* totalLength;
53     const char* sectionLength;
54     long relativeOffset;
55 } grib_accessor_raw;
56 
57 extern grib_accessor_class* grib_accessor_class_gen;
58 
59 static grib_accessor_class _grib_accessor_class_raw = {
60     &grib_accessor_class_gen,  /* super                     */
61     "raw",                     /* name                      */
62     sizeof(grib_accessor_raw), /* size                      */
63     0,                         /* inited */
64     &init_class,               /* init_class */
65     &init,                     /* init                      */
66     0,                         /* post_init                      */
67     0,                         /* free mem                       */
68     0,                         /* describes himself         */
69     0,                         /* get length of section     */
70     0,                         /* get length of string      */
71     &value_count,              /* get number of values      */
72     &byte_count,               /* get number of bytes      */
73     0,                         /* get offset to bytes           */
74     &get_native_type,          /* get native type               */
75     0,                         /* get sub_section                */
76     0,                         /* grib_pack procedures long      */
77     0,                         /* grib_pack procedures long      */
78     0,                         /* grib_pack procedures long      */
79     0,                         /* grib_unpack procedures long    */
80     0,                         /* grib_pack procedures double    */
81     0,                         /* grib_unpack procedures double  */
82     0,                         /* grib_pack procedures string    */
83     0,                         /* grib_unpack procedures string  */
84     0,                         /* grib_pack array procedures string    */
85     0,                         /* grib_unpack array procedures string  */
86     &pack_bytes,               /* grib_pack procedures bytes     */
87     &unpack_bytes,             /* grib_unpack procedures bytes   */
88     0,                         /* pack_expression */
89     0,                         /* notify_change   */
90     &update_size,              /* update_size   */
91     0,                         /* preferred_size   */
92     0,                         /* resize   */
93     0,                         /* nearest_smaller_value */
94     0,                         /* next accessor    */
95     &compare,                  /* compare vs. another accessor   */
96     0,                         /* unpack only ith value          */
97     0,                         /* unpack a subarray         */
98     0,                         /* clear          */
99     0,                         /* clone accessor          */
100 };
101 
102 
103 grib_accessor_class* grib_accessor_class_raw = &_grib_accessor_class_raw;
104 
105 
init_class(grib_accessor_class * c)106 static void init_class(grib_accessor_class* c)
107 {
108     c->dump                   = (*(c->super))->dump;
109     c->next_offset            = (*(c->super))->next_offset;
110     c->string_length          = (*(c->super))->string_length;
111     c->byte_offset            = (*(c->super))->byte_offset;
112     c->sub_section            = (*(c->super))->sub_section;
113     c->pack_missing           = (*(c->super))->pack_missing;
114     c->is_missing             = (*(c->super))->is_missing;
115     c->pack_long              = (*(c->super))->pack_long;
116     c->unpack_long            = (*(c->super))->unpack_long;
117     c->pack_double            = (*(c->super))->pack_double;
118     c->unpack_double          = (*(c->super))->unpack_double;
119     c->pack_string            = (*(c->super))->pack_string;
120     c->unpack_string          = (*(c->super))->unpack_string;
121     c->pack_string_array      = (*(c->super))->pack_string_array;
122     c->unpack_string_array    = (*(c->super))->unpack_string_array;
123     c->pack_expression        = (*(c->super))->pack_expression;
124     c->notify_change          = (*(c->super))->notify_change;
125     c->preferred_size         = (*(c->super))->preferred_size;
126     c->resize                 = (*(c->super))->resize;
127     c->nearest_smaller_value  = (*(c->super))->nearest_smaller_value;
128     c->next                   = (*(c->super))->next;
129     c->unpack_double_element  = (*(c->super))->unpack_double_element;
130     c->unpack_double_subarray = (*(c->super))->unpack_double_subarray;
131     c->clear                  = (*(c->super))->clear;
132     c->make_clone             = (*(c->super))->make_clone;
133 }
134 
135 /* END_CLASS_IMP */
136 
init(grib_accessor * a,const long len,grib_arguments * arg)137 static void init(grib_accessor* a, const long len, grib_arguments* arg)
138 {
139     int n   = 0;
140     int err = 0;
141     long sectionLength;
142     grib_accessor_raw* self = (grib_accessor_raw*)a;
143     grib_expression* e;
144     grib_handle* hand = grib_handle_of_accessor(a);
145 
146     a->length           = 0;
147     self->totalLength   = grib_arguments_get_name(hand, arg, n++);
148     self->sectionLength = grib_arguments_get_name(hand, arg, n++);
149 
150     e   = grib_arguments_get_expression(hand, arg, n++);
151     err = grib_expression_evaluate_long(hand, e, &(self->relativeOffset));
152     if (err)
153         grib_context_log(hand->context, GRIB_LOG_ERROR, "unable to evaluate relativeOffset");
154 
155     grib_get_long(hand, self->sectionLength, &sectionLength);
156 
157     a->length = sectionLength - self->relativeOffset;
158     if (a->length < 0)
159         a->length = 0;
160 
161     /* Assert(a->length>=0); */
162 }
163 
get_native_type(grib_accessor * a)164 static int get_native_type(grib_accessor* a)
165 {
166     return GRIB_TYPE_BYTES;
167 }
168 
169 
compare(grib_accessor * a,grib_accessor * b)170 static int compare(grib_accessor* a, grib_accessor* b)
171 {
172     int retval = GRIB_SUCCESS;
173 
174     size_t alen = (size_t)grib_byte_count(a);
175     size_t blen = (size_t)grib_byte_count(b);
176 
177     if (alen != blen)
178         return GRIB_COUNT_MISMATCH;
179 
180     return retval;
181 }
182 
byte_count(grib_accessor * a)183 static long byte_count(grib_accessor* a)
184 {
185     return a->length;
186 }
187 
value_count(grib_accessor * a,long * len)188 static int value_count(grib_accessor* a, long* len)
189 {
190     *len = a->length;
191     return 0;
192 }
193 
unpack_bytes(grib_accessor * a,unsigned char * buffer,size_t * len)194 static int unpack_bytes(grib_accessor* a, unsigned char* buffer, size_t* len)
195 {
196     if (*len < a->length) {
197         *len = a->length;
198         return GRIB_ARRAY_TOO_SMALL;
199     }
200     *len = a->length;
201 
202     memcpy(buffer, grib_handle_of_accessor(a)->buffer->data + a->offset, *len);
203 
204     return GRIB_SUCCESS;
205 }
206 
update_size(grib_accessor * a,size_t s)207 static void update_size(grib_accessor* a, size_t s)
208 {
209     grib_context_log(a->context, GRIB_LOG_DEBUG, "updating size of %s old %ld new %ld", a->name, a->length, s);
210     a->length = s;
211     Assert(a->length >= 0);
212 }
213 
accessor_raw_set_length(grib_accessor * a,size_t len)214 void accessor_raw_set_length(grib_accessor* a, size_t len)
215 {
216     a->length = len;
217 }
218 
accessor_raw_get_offset(grib_accessor * a)219 long accessor_raw_get_offset(grib_accessor* a)
220 {
221     return a->offset;
222 }
223 
pack_bytes(grib_accessor * a,const unsigned char * val,size_t * len)224 static int pack_bytes(grib_accessor* a, const unsigned char* val, size_t* len)
225 {
226     size_t length = *len;
227     long totalLength;
228     long sectionLength;
229     grib_handle* h          = grib_handle_of_accessor(a);
230     grib_accessor_raw* self = (grib_accessor_raw*)a;
231     long dlen               = length - a->length;
232 
233     grib_get_long(h, self->totalLength, &totalLength);
234     totalLength += dlen;
235     grib_get_long(h, self->sectionLength, &sectionLength);
236     sectionLength += dlen;
237 
238     grib_buffer_replace(a, val, length, 1, 1);
239 
240     grib_set_long(h, self->totalLength, totalLength);
241     grib_set_long(h, self->sectionLength, sectionLength);
242     a->length = length;
243 
244     return GRIB_SUCCESS;
245 }
246