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