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, §ionLength);
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, §ionLength);
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