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 /************************************
12 * Enrico Fucile
13 ************************************/
14
15 #include "grib_api_internal.h"
16 /*
17 This is used by make_class.pl
18
19 START_CLASS_DEF
20 CLASS = accessor
21 SUPER = grib_accessor_class_gen
22 IMPLEMENTS = pack_long;
23 IMPLEMENTS = unpack_long
24 IMPLEMENTS = init;get_native_type
25 MEMBERS = const char* values
26 MEMBERS = const char* Ni
27 MEMBERS = const char* Nj
28 MEMBERS = const char* i_scans_negatively
29 MEMBERS = const char* j_scans_positively
30 MEMBERS = const char* first
31 MEMBERS = const char* last
32 MEMBERS = const char* axis
33 END_CLASS_DEF
34
35 */
36
37 /* START_CLASS_IMP */
38
39 /*
40
41 Don't edit anything between START_CLASS_IMP and END_CLASS_IMP
42 Instead edit values between START_CLASS_DEF and END_CLASS_DEF
43 or edit "accessor.class" and rerun ./make_class.pl
44
45 */
46
47 static int get_native_type(grib_accessor*);
48 static int pack_long(grib_accessor*, const long* val, size_t* len);
49 static int unpack_long(grib_accessor*, long* val, size_t* len);
50 static void init(grib_accessor*, const long, grib_arguments*);
51 static void init_class(grib_accessor_class*);
52
53 typedef struct grib_accessor_change_scanning_direction
54 {
55 grib_accessor att;
56 /* Members defined in gen */
57 /* Members defined in change_scanning_direction */
58 const char* values;
59 const char* Ni;
60 const char* Nj;
61 const char* i_scans_negatively;
62 const char* j_scans_positively;
63 const char* first;
64 const char* last;
65 const char* axis;
66 } grib_accessor_change_scanning_direction;
67
68 extern grib_accessor_class* grib_accessor_class_gen;
69
70 static grib_accessor_class _grib_accessor_class_change_scanning_direction = {
71 &grib_accessor_class_gen, /* super */
72 "change_scanning_direction", /* name */
73 sizeof(grib_accessor_change_scanning_direction), /* size */
74 0, /* inited */
75 &init_class, /* init_class */
76 &init, /* init */
77 0, /* post_init */
78 0, /* free mem */
79 0, /* describes himself */
80 0, /* get length of section */
81 0, /* get length of string */
82 0, /* get number of values */
83 0, /* get number of bytes */
84 0, /* get offset to bytes */
85 &get_native_type, /* get native type */
86 0, /* get sub_section */
87 0, /* grib_pack procedures long */
88 0, /* grib_pack procedures long */
89 &pack_long, /* grib_pack procedures long */
90 &unpack_long, /* grib_unpack procedures long */
91 0, /* grib_pack procedures double */
92 0, /* grib_unpack procedures double */
93 0, /* grib_pack procedures string */
94 0, /* grib_unpack procedures string */
95 0, /* grib_pack array procedures string */
96 0, /* grib_unpack array procedures string */
97 0, /* grib_pack procedures bytes */
98 0, /* grib_unpack procedures bytes */
99 0, /* pack_expression */
100 0, /* notify_change */
101 0, /* update_size */
102 0, /* preferred_size */
103 0, /* resize */
104 0, /* nearest_smaller_value */
105 0, /* next accessor */
106 0, /* compare vs. another accessor */
107 0, /* unpack only ith value */
108 0, /* unpack a subarray */
109 0, /* clear */
110 0, /* clone accessor */
111 };
112
113
114 grib_accessor_class* grib_accessor_class_change_scanning_direction = &_grib_accessor_class_change_scanning_direction;
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->value_count = (*(c->super))->value_count;
123 c->byte_count = (*(c->super))->byte_count;
124 c->byte_offset = (*(c->super))->byte_offset;
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_double = (*(c->super))->pack_double;
129 c->unpack_double = (*(c->super))->unpack_double;
130 c->pack_string = (*(c->super))->pack_string;
131 c->unpack_string = (*(c->super))->unpack_string;
132 c->pack_string_array = (*(c->super))->pack_string_array;
133 c->unpack_string_array = (*(c->super))->unpack_string_array;
134 c->pack_bytes = (*(c->super))->pack_bytes;
135 c->unpack_bytes = (*(c->super))->unpack_bytes;
136 c->pack_expression = (*(c->super))->pack_expression;
137 c->notify_change = (*(c->super))->notify_change;
138 c->update_size = (*(c->super))->update_size;
139 c->preferred_size = (*(c->super))->preferred_size;
140 c->resize = (*(c->super))->resize;
141 c->nearest_smaller_value = (*(c->super))->nearest_smaller_value;
142 c->next = (*(c->super))->next;
143 c->compare = (*(c->super))->compare;
144 c->unpack_double_element = (*(c->super))->unpack_double_element;
145 c->unpack_double_subarray = (*(c->super))->unpack_double_subarray;
146 c->clear = (*(c->super))->clear;
147 c->make_clone = (*(c->super))->make_clone;
148 }
149
150 /* END_CLASS_IMP */
151
init(grib_accessor * a,const long len,grib_arguments * args)152 static void init(grib_accessor* a, const long len, grib_arguments* args)
153 {
154 int n = 0;
155 grib_accessor_change_scanning_direction* self = (grib_accessor_change_scanning_direction*)a;
156
157 self->values = grib_arguments_get_name(grib_handle_of_accessor(a), args, n++);
158 self->Ni = grib_arguments_get_name(grib_handle_of_accessor(a), args, n++);
159 self->Nj = grib_arguments_get_name(grib_handle_of_accessor(a), args, n++);
160 self->i_scans_negatively = grib_arguments_get_name(grib_handle_of_accessor(a), args, n++);
161 self->j_scans_positively = grib_arguments_get_name(grib_handle_of_accessor(a), args, n++);
162 self->first = grib_arguments_get_name(grib_handle_of_accessor(a), args, n++);
163 self->last = grib_arguments_get_name(grib_handle_of_accessor(a), args, n++);
164 self->axis = grib_arguments_get_name(grib_handle_of_accessor(a), args, n++);
165
166 a->flags |= GRIB_ACCESSOR_FLAG_FUNCTION;
167 a->length = 0;
168 }
169
pack_long(grib_accessor * a,const long * val,size_t * len)170 static int pack_long(grib_accessor* a, const long* val, size_t* len)
171 {
172 int ret = 0;
173 long i, j, jr, theEnd, Ni, Nj, k, kp;
174 double tmp;
175 long iScansNegatively = 0;
176 long jScansPositively = 0;
177 double first = 0;
178 double last = 0;
179 size_t size = 0;
180 double* values = NULL;
181 grib_accessor_change_scanning_direction* self = (grib_accessor_change_scanning_direction*)a;
182 grib_context* c = a->context;
183 grib_handle* h = grib_handle_of_accessor(a);
184
185 if (*val == 0)
186 return 0;
187
188 if ((ret = grib_get_long_internal(h, self->Ni, &Ni)) != GRIB_SUCCESS)
189 return ret;
190 if ((ret = grib_get_long_internal(h, self->Nj, &Nj)) != GRIB_SUCCESS)
191 return ret;
192
193 if ((ret = grib_get_long_internal(h, self->i_scans_negatively, &iScansNegatively)) != GRIB_SUCCESS)
194 return ret;
195 if ((ret = grib_get_long_internal(h, self->j_scans_positively, &jScansPositively)) != GRIB_SUCCESS)
196 return ret;
197
198 if ((ret = grib_get_double_internal(h, self->first, &first)) != GRIB_SUCCESS)
199 return ret;
200 if ((ret = grib_get_double_internal(h, self->last, &last)) != GRIB_SUCCESS)
201 return ret;
202
203 if ((ret = grib_get_size(h, self->values, &size)) != GRIB_SUCCESS)
204 return ret;
205
206 if (size > Ni * Nj) {
207 grib_context_log(c, GRIB_LOG_ERROR, "change_scanning_direction: wrong values size!=Ni*Nj (%ld!=%ld*%ld)", size, Ni, Nj);
208 return GRIB_WRONG_ARRAY_SIZE;
209 }
210
211 values = (double*)grib_context_malloc(c, size * sizeof(double));
212 if (!values)
213 return GRIB_OUT_OF_MEMORY;
214
215 if ((ret = grib_get_double_array_internal(h, self->values, values, &size)) != GRIB_SUCCESS) {
216 grib_context_free(c, values);
217 return ret;
218 }
219
220 if (self->axis[0] == 'x') {
221 theEnd = (Ni + 0.5) / 2;
222 for (j = 0; j < Nj; j++) {
223 jr = Ni * j;
224 for (i = 0; i < theEnd; i++) {
225 k = jr + i;
226 kp = jr + Ni - i - 1;
227 tmp = values[k];
228 values[k] = values[kp];
229 values[kp] = tmp;
230 }
231 }
232 iScansNegatively = !iScansNegatively;
233 if ((ret = grib_set_long_internal(h, self->i_scans_negatively, iScansNegatively)) != GRIB_SUCCESS)
234 return ret;
235 }
236 else {
237 long kpj;
238 theEnd = (Nj + 0.5) / 2;
239 for (i = 0; i < Ni; i++) {
240 kpj = Ni * (Nj - 1);
241 for (j = 0; j < theEnd; j++) {
242 k = Ni * j + i;
243 kp = kpj - Ni * j + i;
244 tmp = values[k];
245 values[k] = values[kp];
246 values[kp] = tmp;
247 }
248 }
249 jScansPositively = !jScansPositively;
250 if ((ret = grib_set_long_internal(h, self->j_scans_positively, jScansPositively)) != GRIB_SUCCESS)
251 return ret;
252 }
253
254 if ((ret = grib_set_double_array_internal(h, self->values, values, size)) != GRIB_SUCCESS) {
255 grib_context_free(c, values);
256 return ret;
257 }
258
259 if ((ret = grib_set_double_internal(h, self->first, last)) != GRIB_SUCCESS)
260 return ret;
261
262 if ((ret = grib_set_double_internal(h, self->last, first)) != GRIB_SUCCESS)
263 return ret;
264
265 grib_context_free(c, values);
266
267 return GRIB_SUCCESS;
268 }
269
get_native_type(grib_accessor * a)270 static int get_native_type(grib_accessor* a)
271 {
272 return GRIB_TYPE_LONG;
273 }
274
unpack_long(grib_accessor * a,long * v,size_t * len)275 static int unpack_long(grib_accessor* a, long* v, size_t* len)
276 {
277 /* ECC-976: decoding this accessor doesn't make sense so we return a dummy value */
278 *v = -1;
279 return GRIB_SUCCESS;
280 }
281