* src/vm/array.c (array_##name##array_element_get): Fixed
[cacao.git] / src / vm / array.c
1 /* src/vm/array.c - Java array functions
2
3    Copyright (C) 2007
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <stdint.h>
29
30 #include "native/llni.h"
31
32 #include "vm/array.h"
33 #include "vm/exceptions.h"
34 #include "vm/global.h"
35 #include "vm/primitive.h"
36 #include "vm/vm.h"
37
38
39 /* array_element_get ***********************************************************
40
41    Returns a boxed element of the given Java array.
42
43 *******************************************************************************/
44
45 java_handle_t *array_element_get(java_handle_t *a, int32_t index)
46 {
47         vftbl_t       *v;
48         int            type;
49         imm_union      value;
50         java_handle_t *o;
51
52         v = LLNI_vftbl_direct(a);
53
54         type = v->arraydesc->arraytype;
55
56         value = array_element_primitive_get(a, index);
57
58         o = primitive_box(type, value);
59
60         return o;
61 }
62
63
64 /* array_element_set ***********************************************************
65
66    Sets a boxed element in the given Java array.
67
68 *******************************************************************************/
69
70 void array_element_set(java_handle_t *a, int32_t index, java_handle_t *o)
71 {
72         imm_union value;
73
74         value = primitive_unbox(o);
75
76         array_element_primitive_set(a, index, value);
77 }
78
79
80 /* array_element_primitive_get *************************************************
81
82    Returns a primitive element of the given Java array.
83
84 *******************************************************************************/
85
86 imm_union array_element_primitive_get(java_handle_t *a, int32_t index)
87 {
88         vftbl_t  *v;
89         int       type;
90         imm_union value;
91
92         v = LLNI_vftbl_direct(a);
93
94         type = v->arraydesc->arraytype;
95
96         switch (type) {
97         case ARRAYTYPE_BOOLEAN:
98                 value.i = array_booleanarray_element_get((java_handle_booleanarray_t *) a, index);
99                 break;
100         case ARRAYTYPE_BYTE:
101                 value.i = array_bytearray_element_get((java_handle_bytearray_t *) a,
102                                                                                           index);
103                 break;
104         case ARRAYTYPE_CHAR:
105                 value.i = array_chararray_element_get((java_handle_chararray_t *) a,
106                                                                                           index);
107                 break;
108         case ARRAYTYPE_SHORT:
109                 value.i = array_shortarray_element_get((java_handle_shortarray_t *) a,
110                                                                                            index);
111                 break;
112         case ARRAYTYPE_INT:
113                 value.i = array_intarray_element_get((java_handle_intarray_t *) a,
114                                                                                          index);
115                 break;
116         case ARRAYTYPE_LONG:
117                 value.l = array_longarray_element_get((java_handle_longarray_t *) a,
118                                                                                           index);
119                 break;
120         case ARRAYTYPE_FLOAT:
121                 value.f = array_floatarray_element_get((java_handle_floatarray_t *) a,
122                                                                                            index);
123                 break;
124         case ARRAYTYPE_DOUBLE:
125                 value.d = array_doublearray_element_get((java_handle_doublearray_t *) a,
126                                                                                                 index);
127                 break;
128         case ARRAYTYPE_OBJECT:
129                 value.a = array_objectarray_element_get((java_handle_objectarray_t *) a,
130                                                                                                 index);
131                 break;
132         default:
133                 vm_abort("array_element_primitive_get: invalid array element type %d",
134                                  type);
135         }
136
137         return value;
138 }
139
140
141 /* array_element_primitive_set *************************************************
142
143    Sets a primitive element in the given Java array.
144
145 *******************************************************************************/
146
147 void array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value)
148 {
149         vftbl_t *v;
150         int      type;
151
152         v = LLNI_vftbl_direct(a);
153
154         type = v->arraydesc->arraytype;
155
156         switch (type) {
157         case ARRAYTYPE_BOOLEAN:
158                 array_booleanarray_element_set((java_handle_booleanarray_t *) a,
159                                                                            index, value.i);
160                 break;
161         case ARRAYTYPE_BYTE:
162                 array_bytearray_element_set((java_handle_bytearray_t *) a,
163                                                                         index, value.i);
164                 break;
165         case ARRAYTYPE_CHAR:
166                 array_chararray_element_set((java_handle_chararray_t *) a,
167                                                                         index, value.i);
168                 break;
169         case ARRAYTYPE_SHORT:
170                 array_shortarray_element_set((java_handle_shortarray_t *) a,
171                                                                          index, value.i);
172                 break;
173         case ARRAYTYPE_INT:
174                 array_intarray_element_set((java_handle_intarray_t *) a,
175                                                                    index, value.i);
176                 break;
177         case ARRAYTYPE_LONG:
178                 array_longarray_element_set((java_handle_longarray_t *) a,
179                                                                         index, value.l);
180                 break;
181         case ARRAYTYPE_FLOAT:
182                 array_floatarray_element_set((java_handle_floatarray_t *) a,
183                                                                          index, value.f);
184                 break;
185         case ARRAYTYPE_DOUBLE:
186                 array_doublearray_element_set((java_handle_doublearray_t *) a,
187                                                                           index, value.d);
188                 break;
189         case ARRAYTYPE_OBJECT:
190                 array_objectarray_element_set((java_handle_objectarray_t *) a,
191                                                                           index, value.a);
192                 break;
193         default:
194                 vm_abort("array_element_primitive_set: invalid array element type %d",
195                                  type);
196         }
197 }
198
199
200 /* array_xxxarray_element_get **************************************************
201
202    Returns a primitive element of the given Java array.
203
204 *******************************************************************************/
205
206 #define ARRAY_TYPEARRAY_ELEMENT_GET(name, type)                                \
207 type array_##name##array_element_get(java_handle_##name##array_t *a, int32_t index) \
208 {                                                                              \
209         type    value;                                                             \
210         int32_t size;                                                              \
211                                                                                \
212         if (a == NULL) {                                                           \
213                 exceptions_throw_nullpointerexception();                               \
214                 return (type) 0;                                                       \
215         }                                                                          \
216                                                                                \
217         size = LLNI_array_size(a);                                                 \
218                                                                                \
219         if ((index < 0) || (index >= size)) {                                      \
220                 exceptions_throw_arrayindexoutofboundsexception();                     \
221                 return (type) 0;                                                       \
222         }                                                                          \
223                                                                                \
224         value = LLNI_array_direct(a, index);                                       \
225                                                                                \
226         return value;                                                              \
227 }
228
229 java_handle_t *array_objectarray_element_get(java_handle_objectarray_t *a, int32_t index)
230 {
231         java_handle_t *value;
232         int32_t size;
233
234         if (a == NULL) {
235                 exceptions_throw_nullpointerexception();
236                 return NULL;
237         }
238
239         size = LLNI_array_size(a);
240
241         if ((index < 0) || (index >= size)) {
242                 exceptions_throw_arrayindexoutofboundsexception();
243                 return NULL;
244         }
245
246         LLNI_CRITICAL_START;
247         value = LLNI_WRAP(LLNI_array_direct(a, index));
248         LLNI_CRITICAL_END;
249
250         return value;
251 }
252
253 ARRAY_TYPEARRAY_ELEMENT_GET(boolean, uint8_t)
254 ARRAY_TYPEARRAY_ELEMENT_GET(byte,    int8_t)
255 ARRAY_TYPEARRAY_ELEMENT_GET(char,    uint16_t)
256 ARRAY_TYPEARRAY_ELEMENT_GET(short,   int16_t)
257 ARRAY_TYPEARRAY_ELEMENT_GET(int,     int32_t)
258 ARRAY_TYPEARRAY_ELEMENT_GET(long,    int64_t)
259 ARRAY_TYPEARRAY_ELEMENT_GET(float,   float)
260 ARRAY_TYPEARRAY_ELEMENT_GET(double,  double)
261
262
263 /* array_xxxarray_element_set **************************************************
264
265    Sets a primitive element in the given Java array.
266
267 *******************************************************************************/
268
269 #define ARRAY_TYPEARRAY_ELEMENT_SET(name, type)                                \
270 void array_##name##array_element_set(java_handle_##name##array_t *a, int32_t index, type value) \
271 {                                                                              \
272         int32_t size;                                                              \
273                                                                                \
274         if (a == NULL) {                                                           \
275                 exceptions_throw_nullpointerexception();                               \
276                 return;                                                                \
277         }                                                                          \
278                                                                                \
279         size = LLNI_array_size(a);                                                 \
280                                                                                \
281         if ((index < 0) || (index >= size)) {                                      \
282                 exceptions_throw_arrayindexoutofboundsexception();                     \
283                 return;                                                                \
284         }                                                                          \
285                                                                                \
286         LLNI_array_direct(a, index) = value;                                       \
287 }
288
289 void array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value)
290 {
291         int32_t size;
292
293         if (a == NULL) {
294                 exceptions_throw_nullpointerexception();
295                 return;
296         }
297
298         size = LLNI_array_size(a);
299
300         if ((index < 0) || (index >= size)) {
301                 exceptions_throw_arrayindexoutofboundsexception();
302                 return;
303         }
304
305         LLNI_CRITICAL_START;
306         LLNI_array_direct(a, index) = LLNI_UNWRAP(value);
307         LLNI_CRITICAL_END;
308 }
309
310 ARRAY_TYPEARRAY_ELEMENT_SET(boolean, uint8_t)
311 ARRAY_TYPEARRAY_ELEMENT_SET(byte,    int8_t)
312 ARRAY_TYPEARRAY_ELEMENT_SET(char,    uint16_t)
313 ARRAY_TYPEARRAY_ELEMENT_SET(short,   int16_t)
314 ARRAY_TYPEARRAY_ELEMENT_SET(int,     int32_t)
315 ARRAY_TYPEARRAY_ELEMENT_SET(long,    int64_t)
316 ARRAY_TYPEARRAY_ELEMENT_SET(float,   float)
317 ARRAY_TYPEARRAY_ELEMENT_SET(double,  double)
318
319
320 /* array_length_get ***********************************************************
321
322    Returns a the length of the given Java array.
323
324    ARGUMENTS:
325        a ... Java array
326
327    RETURN VALUE:
328         0 ... exception thrown
329            >0 ... length of the Java array
330
331 *******************************************************************************/
332
333 int32_t array_length_get(java_handle_t *a)
334 {
335         classinfo *c;
336         int32_t    size;
337
338         if (a == NULL) {
339                 exceptions_throw_nullpointerexception();
340                 return 0;
341         }
342
343         LLNI_class_get(a, c);
344
345         if (!class_is_array(c)) {
346 /*              exceptions_throw_illegalargumentexception("Argument is not an array"); */
347                 exceptions_throw_illegalargumentexception();
348                 return 0;
349         }
350
351         size = LLNI_array_size(a);
352
353         if ((size <= 0) || (size > /* MAX_DIM */ 255)) {
354                 exceptions_throw_illegalargumentexception();
355                 return 0;
356         }
357
358         return size;
359 }
360
361
362 /*
363  * These are local overrides for various environment variables in Emacs.
364  * Please do not remove this and leave it at the end of the file, where
365  * Emacs will automagically detect them.
366  * ---------------------------------------------------------------------
367  * Local variables:
368  * mode: c
369  * indent-tabs-mode: t
370  * c-basic-offset: 4
371  * tab-width: 4
372  * End:
373  * vim:noexpandtab:sw=4:ts=4:
374  */