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