* src/vm/array.hpp: Implemented array access classes in C++.
[cacao.git] / src / vm / array.cpp
1 /* src/vm/array.cpp - Java array functions
2
3    Copyright (C) 2007
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5    Copyright (C) 2008 Theobroma Systems Ltd.
6
7    This file is part of CACAO.
8
9    This program is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2, or (at
12    your option) any later version.
13
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22    02110-1301, USA.
23
24 */
25
26
27 #include "config.h"
28
29 #include <stdint.h>
30
31 #include "native/llni.h"
32
33 #include "vm/array.hpp"
34 #include "vm/exceptions.hpp"
35 #include "vm/global.h"
36 #include "vm/globals.hpp"
37 #include "vm/primitive.hpp"
38 #include "vm/vm.hpp"
39
40
41 /**
42  * Returns a boxed element of the given Java array.
43  */
44 java_handle_t* Array::get_boxed_element(int32_t index)
45 {
46         vftbl_t       *v;
47         int            type;
48         imm_union      value;
49         java_handle_t *o;
50
51         if (is_null()) {
52                 exceptions_throw_nullpointerexception();
53                 return NULL;
54         }
55
56         v = LLNI_vftbl_direct(_handle);
57
58         type = v->arraydesc->arraytype;
59
60         value = get_primitive_element(index);
61
62         o = Primitive::box(type, value);
63
64         return o;
65 }
66
67
68 /**
69  * Sets a boxed element in the given Java array.
70  */
71 void Array::set_boxed_element(int32_t index, java_handle_t *o)
72 {
73         imm_union value;
74
75         value = Primitive::unbox(o);
76
77         set_primitive_element(index, value);
78 }
79
80
81 /**
82  * Returns a primitive element of the given Java array.
83  */
84 imm_union Array::get_primitive_element(int32_t index)
85 {
86         vftbl_t  *v;
87         int       type;
88         imm_union value;
89
90         if (is_null()) {
91                 exceptions_throw_nullpointerexception();
92                 value.a = NULL;
93                 return value;
94         }
95
96         java_handle_array_t* a = _handle;
97
98         v = LLNI_vftbl_direct(a);
99
100         type = v->arraydesc->arraytype;
101
102         switch (type) {
103         case ARRAYTYPE_BOOLEAN:
104                 {
105                         BooleanArray array(a);
106                         value.i = array.get_element(index);
107                 }
108                 break;
109         case ARRAYTYPE_BYTE:
110                 {
111                         ByteArray array(a);
112                         value.i = array.get_element(index);
113                 }
114                 break;
115         case ARRAYTYPE_CHAR:
116                 {
117                         CharArray array(a);
118                         value.i = array.get_element(index);
119                 }
120                 break;
121         case ARRAYTYPE_SHORT:
122                 {
123                         ShortArray array(a);
124                         value.i = array.get_element(index);
125                 }
126                 break;
127         case ARRAYTYPE_INT:
128                 {
129                         IntArray array(a);
130                         value.i = array.get_element(index);
131                 }
132                 break;
133         case ARRAYTYPE_LONG:
134                 {
135                         LongArray array(a);
136                         value.l = array.get_element(index);
137                 }
138                 break;
139         case ARRAYTYPE_FLOAT:
140                 {
141                         FloatArray array(a);
142                         value.f = array.get_element(index);
143                 }
144                 break;
145         case ARRAYTYPE_DOUBLE:
146                 {
147                         DoubleArray array(a);
148                         value.d = array.get_element(index);
149                 }
150                 break;
151         case ARRAYTYPE_OBJECT:
152                 {
153                         ObjectArray array(a);
154                         value.a = array.get_element(index);
155                 }
156                 break;
157         default:
158                 vm_abort("Array::primitive_element_get: invalid array element type %d",
159                                  type);
160         }
161
162         return value;
163 }
164
165
166 /**
167  * Sets a primitive element in the given Java array.
168  */
169 void Array::set_primitive_element(int32_t index, imm_union value)
170 {
171         vftbl_t *v;
172         int      type;
173
174         if (is_null()) {
175                 exceptions_throw_nullpointerexception();
176                 return;
177         }
178
179         java_handle_array_t* a = _handle;
180
181         v = LLNI_vftbl_direct(a);
182
183         type = v->arraydesc->arraytype;
184
185         switch (type) {
186         case ARRAYTYPE_BOOLEAN:
187                 {
188                         BooleanArray array(a);
189                         array.set_element(index, value.i);
190                 }
191                 break;
192         case ARRAYTYPE_BYTE:
193                 {
194                         ByteArray array(a);
195                         array.set_element(index, value.i);
196                 }
197                 break;
198         case ARRAYTYPE_CHAR:
199                 {
200                         CharArray array(a);
201                         array.set_element(index, value.i);
202                 }
203                 break;
204         case ARRAYTYPE_SHORT:
205                 {
206                         ShortArray array(a);
207                         array.set_element(index, value.i);
208                 }
209                 break;
210         case ARRAYTYPE_INT:
211                 {
212                         IntArray array(a);
213                         array.set_element(index, value.i);
214                 }
215                 break;
216         case ARRAYTYPE_LONG:
217                 {
218                         LongArray array(a);
219                         array.set_element(index, value.l);
220                 }
221                 break;
222         case ARRAYTYPE_FLOAT:
223                 {
224                         FloatArray array(a);
225                         array.set_element(index, value.f);
226                 }
227                 break;
228         case ARRAYTYPE_DOUBLE:
229                 {
230                         DoubleArray array(a);
231                         array.set_element(index, value.d);
232                 }
233                 break;
234         case ARRAYTYPE_OBJECT:
235                 {
236                         ObjectArray array(a);
237                         array.set_element(index, static_cast<java_handle_t*>(value.a));
238                 }
239                 break;
240         default:
241                 vm_abort("array_element_primitive_set: invalid array element type %d",
242                                  type);
243         }
244 }
245
246
247 /**
248  * Creates an array of references to the given class type on the heap.
249  * The handle pointer to the array can be NULL in case of an exception.
250  */
251 ObjectArray::ObjectArray(int32_t length, classinfo* componentclass)
252                 : ArrayTemplate<java_handle_t*>(NULL)
253 {
254         // Is class loaded?
255         assert(componentclass->state & CLASS_LOADED);
256
257         // Is class linked?
258         if (!(componentclass->state & CLASS_LINKED))
259                 if (!link_class(componentclass)) {
260                         _handle = NULL;
261                         return;
262                 }
263
264         classinfo* arrayclass = class_array_of(componentclass, true);
265
266         if (arrayclass == NULL) {
267                 _handle = NULL;
268                 return;
269         }
270
271         // Delegate allocation to generic array class
272         Array a(length, arrayclass);
273
274         _handle = a.get_handle();
275 }
276
277
278 /**
279  * Creates an array of references to classinfos on the heap.
280  * The handle pointer to the array can be NULL in case of an exception.
281  */
282 ClassArray::ClassArray(int32_t length)
283                 : ArrayTemplate<classinfo*>(NULL)
284 {
285         // Delegate allocation to object array class
286         ObjectArray oa(length, class_java_lang_Class);
287
288         _handle = oa.get_handle();
289 }
290
291
292 /*
293  * These are local overrides for various environment variables in Emacs.
294  * Please do not remove this and leave it at the end of the file, where
295  * Emacs will automagically detect them.
296  * ---------------------------------------------------------------------
297  * Local variables:
298  * mode: c++
299  * indent-tabs-mode: t
300  * c-basic-offset: 4
301  * tab-width: 4
302  * End:
303  * vim:noexpandtab:sw=4:ts=4:
304  */