pylucene 3.5.0-3
[pylucene.git] / jcc / jcc / sources / JArray.cpp
1 /*
2  *   Licensed under the Apache License, Version 2.0 (the "License");
3  *   you may not use this file except in compliance with the License.
4  *   You may obtain a copy of the License at
5  *
6  *       http://www.apache.org/licenses/LICENSE-2.0
7  *
8  *   Unless required by applicable law or agreed to in writing, software
9  *   distributed under the License is distributed on an "AS IS" BASIS,
10  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  *   See the License for the specific language governing permissions and
12  *   limitations under the License.
13  */
14
15 #ifdef PYTHON
16
17 #include <jni.h>
18 #include <Python.h>
19 #include "structmember.h"
20
21 #include "JArray.h"
22 #include "functions.h"
23 #include "java/lang/Class.h"
24
25 using namespace java::lang;
26
27
28 template<typename T> class _t_JArray : public t_JArray<T> {
29 public:
30     static PyObject *format;
31 };
32
33 template<typename U>
34 static PyObject *get(U *self, Py_ssize_t n)
35 {
36     return self->array.get(n);
37 }
38
39 template<typename U>
40 static PyObject *toSequence(U *self)
41 {
42     return self->array.toSequence();
43 }
44
45 template<typename U>
46 static PyObject *toSequence(U *self, Py_ssize_t lo, Py_ssize_t hi)
47 {
48     return self->array.toSequence(lo, hi);
49 }
50
51 template<typename U> class _t_iterator {
52 public:
53     PyObject_HEAD
54     U *obj;
55     Py_ssize_t position;
56
57     static void dealloc(_t_iterator *self)
58     {
59         Py_XDECREF(self->obj);
60         self->ob_type->tp_free((PyObject *) self);
61     }
62
63     static PyObject *iternext(_t_iterator *self)
64     {
65         if (self->position < (Py_ssize_t) self->obj->array.length)
66             return get<U>(self->obj, self->position++);
67
68         PyErr_SetNone(PyExc_StopIteration);
69         return NULL;
70     }
71
72     static PyTypeObject *JArrayIterator;
73 };
74
75 template<typename T, typename U>
76 static int init(U *self, PyObject *args, PyObject *kwds)
77 {
78     PyObject *obj;
79
80     if (!PyArg_ParseTuple(args, "O", &obj))
81         return -1;
82
83     if (PySequence_Check(obj))
84     {
85         self->array = JArray<T>(obj);
86         if (PyErr_Occurred())
87             return -1;
88     }
89     else if (PyGen_Check(obj))
90     {
91         PyObject *tuple =
92             PyObject_CallFunctionObjArgs((PyObject *) &PyTuple_Type, obj, NULL);
93
94         if (!tuple)
95             return -1;
96
97         self->array = JArray<T>(tuple);
98         Py_DECREF(tuple);
99         if (PyErr_Occurred())
100             return -1;
101     }
102     else if (PyInt_Check(obj))
103     {
104         int n = PyInt_AsLong(obj);
105
106         if (n < 0)
107         {
108             PyErr_SetObject(PyExc_ValueError, obj);
109             return -1;
110         }
111
112         self->array = JArray<T>(n);
113     }
114     else
115     {
116         PyErr_SetObject(PyExc_TypeError, obj);
117         return -1;
118     }
119
120     return 0;
121 }
122
123 template<typename T, typename U>
124 static void dealloc(U *self)
125 {
126     self->array = JArray<T>((jobject) NULL);
127     self->ob_type->tp_free((PyObject *) self);
128 }
129
130 template<typename U>
131 static PyObject *_format(U *self, PyObject *(*fn)(PyObject *))
132 {
133     if (self->array.this$)
134     {
135         PyObject *list = toSequence<U>(self);
136             
137         if (list)
138         {
139             PyObject *result = (*fn)(list);
140
141             Py_DECREF(list);
142             if (result)
143             {
144                 PyObject *args = PyTuple_New(1);
145
146                 PyTuple_SET_ITEM(args, 0, result);
147                 result = PyString_Format(U::format, args);
148                 Py_DECREF(args);
149
150                 return result;
151             }
152         }
153
154         return NULL;
155     }
156
157     return PyString_FromString("<null>");
158 }
159
160 template<typename U>
161 static PyObject *repr(U *self)
162 {
163     return _format(self, (PyObject *(*)(PyObject *)) PyObject_Repr);
164 }
165
166 template<typename U>
167 static PyObject *str(U *self)
168 {
169     return _format(self, (PyObject *(*)(PyObject *)) PyObject_Str);
170 }
171
172 template<typename U>
173 static int _compare(U *self, PyObject *value, int i0, int i1, int op, int *cmp)
174 {
175     PyObject *v0 = get<U>(self, i0);
176     PyObject *v1 = PySequence_Fast_GET_ITEM(value, i1);  /* borrowed */
177
178     if (!v0)
179         return -1;
180
181     if (!v1)
182     {
183         Py_DECREF(v0);
184         return -1;
185     }
186
187     *cmp = PyObject_RichCompareBool(v0, v1, op);
188     Py_DECREF(v0);
189
190     if (*cmp < 0)
191         return -1;
192
193     return 0;
194 }
195
196 template<typename U>
197 static PyObject *richcompare(U *self, PyObject *value, int op)
198 {
199     PyObject *result = NULL;
200     int s0, s1;
201
202     if (!PySequence_Check(value))
203     {
204         Py_INCREF(Py_NotImplemented);
205         return Py_NotImplemented;
206     }
207
208     value = PySequence_Fast(value, "not a sequence");
209     if (!value)
210         return NULL;
211
212     s0 = PySequence_Fast_GET_SIZE(value);
213     s1 = self->array.length;
214
215     if (s1 < 0)
216     {
217         Py_DECREF(value);
218         return NULL;
219     }
220
221     if (s0 != s1)
222     {
223         switch (op) {
224           case Py_EQ: result = Py_False; break;
225           case Py_NE: result = Py_True; break;
226         }
227     }
228
229     if (!result)
230     {
231         int i0, i1, cmp = 1;
232
233         for (i0 = 0, i1 = 0; i0 < s0 && i1 < s1 && cmp; i0++, i1++) {
234             if (_compare(self, value, i0, i1, Py_EQ, &cmp) < 0)
235             {
236                 Py_DECREF(value);
237                 return NULL;
238             }                
239         }
240
241         if (cmp)
242         {
243             switch (op) {
244               case Py_LT: cmp = s0 < s1; break;
245               case Py_LE: cmp = s0 <= s1; break;
246               case Py_EQ: cmp = s0 == s1; break;
247               case Py_NE: cmp = s0 != s1; break;
248               case Py_GT: cmp = s0 > s1; break;
249               case Py_GE: cmp = s0 >= s1; break;
250               default: cmp = 0;
251             }
252
253             result = cmp ? Py_True : Py_False;
254         }
255         else if (op == Py_EQ)
256             result = Py_False;
257         else if (op == Py_NE)
258             result = Py_True;
259         else if (_compare(self, value, i0, i1, op, &cmp) < 0)
260         {
261             Py_DECREF(value);
262             return NULL;
263         }
264         else
265             result = cmp ? Py_True : Py_False;
266     }
267     Py_DECREF(value);
268
269     Py_INCREF(result);
270     return result;
271 }
272
273 template<typename U>
274 static PyObject *iter(U *self)
275 {
276     _t_iterator<U> *it =
277         PyObject_New(_t_iterator<U>, _t_iterator<U>::JArrayIterator);
278
279     if (it)
280     {
281         it->position = 0;
282         it->obj = self; Py_INCREF((PyObject *) self);
283     }
284
285     return (PyObject *) it;
286 }
287
288 template<typename U>
289 static Py_ssize_t seq_length(U *self)
290 {
291     if (self->array.this$)
292         return self->array.length;
293
294     return 0;
295 }
296
297 template<typename U>
298 static PyObject *seq_get(U *self, Py_ssize_t n)
299 {
300     return get<U>(self, n);
301 }
302
303 template<typename U>
304 static int seq_contains(U *self, PyObject *value)
305 {
306     return 0;
307 }
308
309 template<typename U>
310 static PyObject *seq_concat(U *self, PyObject *arg)
311 {
312     PyObject *list = toSequence<U>(self);
313
314     if (list != NULL &&
315         PyList_Type.tp_as_sequence->sq_inplace_concat(list, arg) < 0)
316     {
317         Py_DECREF(list);
318         return NULL;
319     }
320
321     return list;
322 }
323
324 template<typename U>
325 static PyObject *seq_repeat(U *self, Py_ssize_t n)
326 {
327     PyObject *list = toSequence<U>(self);
328
329     if (list != NULL &&
330         PyList_Type.tp_as_sequence->sq_inplace_repeat(list, n) < 0)
331     {
332         Py_DECREF(list);
333         return NULL;
334     }
335
336     return list;
337 }
338
339 template<typename U>
340 static PyObject *seq_getslice(U *self, Py_ssize_t lo, Py_ssize_t hi)
341 {
342     return toSequence<U>(self, lo, hi);
343 }
344
345 template<typename U>
346 static int seq_set(U *self, Py_ssize_t n, PyObject *value)
347 {
348     return self->array.set(n, value);
349 }
350
351 template<typename U>
352 static int seq_setslice(U *self, Py_ssize_t lo, Py_ssize_t hi, PyObject *values)
353 {
354     Py_ssize_t length = self->array.length;
355
356     if (values == NULL)
357     {
358         PyErr_SetString(PyExc_ValueError, "array size cannot change");
359         return -1;
360     }
361             
362     if (lo < 0) lo = length + lo;
363     if (lo < 0) lo = 0;
364     else if (lo > length) lo = length;
365     if (hi < 0) hi = length + hi;
366     if (hi < 0) hi = 0;
367     else if (hi > length) hi = length;
368     if (lo > hi) lo = hi;
369
370     PyObject *sequence = PySequence_Fast(values, "not a sequence");
371     if (!sequence)
372         return -1;
373
374     Py_ssize_t size = PySequence_Fast_GET_SIZE(sequence);
375     if (size < 0)
376         goto error;
377
378     if (size != hi - lo)
379     {
380         PyErr_SetString(PyExc_ValueError, "array size cannot change");
381         goto error;
382     }
383
384     for (Py_ssize_t i = lo; i < hi; i++) {
385         PyObject *value = PySequence_Fast_GET_ITEM(sequence, i - lo);
386
387         if (value == NULL)
388             goto error;
389
390         if (self->array.set(i, value) < 0)
391             goto error;
392     }
393
394     Py_DECREF(sequence);
395     return 0;
396
397   error:
398     Py_DECREF(sequence);
399     return -1;
400 }
401
402 template<typename T> 
403 static jclass initializeClass(void)
404 {
405     return env->get_vm_env()->GetObjectClass(JArray<T>((Py_ssize_t) 0).this$);
406 }
407
408 template<typename T> 
409 static PyObject *cast_(PyTypeObject *type, PyObject *args, PyObject *kwds)
410 {
411     PyObject *arg, *clsObj;
412
413     if (!PyArg_ParseTuple(args, "O", &arg))
414         return NULL;
415
416     if (!PyObject_TypeCheck(arg, &PY_TYPE(Object)))
417     {
418         PyErr_SetObject(PyExc_TypeError, arg);
419         return NULL;
420     }
421
422     Class argCls = ((t_Object *) arg)->object.getClass();
423
424     if (!argCls.isArray())
425     {
426         PyErr_SetObject(PyExc_TypeError, arg);
427         return NULL;
428     }
429
430     clsObj = PyObject_GetAttrString((PyObject *) type, "class_");
431     if (!clsObj)
432         return NULL;
433
434     Class arrayCls = ((t_Class *) clsObj)->object;
435
436     if (!arrayCls.isAssignableFrom(argCls))
437     {
438         PyErr_SetObject(PyExc_TypeError, arg);
439         return NULL;
440     }
441
442     return JArray<T>(((t_JObject *) arg)->object.this$).wrap();
443 }
444
445 template<typename T> 
446 static PyObject *instance_(PyTypeObject *type, PyObject *args, PyObject *kwds)
447 {
448     PyObject *arg, *clsObj;
449
450     if (!PyArg_ParseTuple(args, "O", &arg))
451         return NULL;
452
453     if (!PyObject_TypeCheck(arg, &PY_TYPE(Object)))
454         Py_RETURN_FALSE;
455
456     Class argCls = ((t_Object *) arg)->object.getClass();
457
458     if (!argCls.isArray())
459         Py_RETURN_FALSE;
460
461     clsObj = PyObject_GetAttrString((PyObject *) type, "class_");
462     if (!clsObj)
463         return NULL;
464
465     Class arrayCls = ((t_Class *) clsObj)->object;
466
467     if (!arrayCls.isAssignableFrom(argCls))
468         Py_RETURN_FALSE;
469
470     Py_RETURN_TRUE;
471 }
472
473 template<typename T> 
474 static PyObject *assignable_(PyTypeObject *type, PyObject *args, PyObject *kwds)
475 {
476     return instance_<T>(type, args, kwds);
477 }
478
479 template< typename T, typename U = _t_JArray<T> > class jarray_type {
480 public:
481     PySequenceMethods seq_methods;
482     PyTypeObject type_object;
483
484     class iterator_type {
485     public:
486         PyTypeObject type_object;
487
488         void install(char *name, PyObject *module)
489         {
490             type_object.tp_name = name;
491
492             if (PyType_Ready(&type_object) == 0)
493             {
494                 Py_INCREF((PyObject *) &type_object);
495                 PyModule_AddObject(module, name, (PyObject *) &type_object);
496             }
497
498             _t_iterator<U>::JArrayIterator = &type_object;
499         }
500
501         iterator_type()
502         {
503             memset(&type_object, 0, sizeof(type_object));
504
505             type_object.ob_refcnt = 1;
506             type_object.ob_type = NULL;
507             type_object.tp_basicsize = sizeof(_t_iterator<U>);
508             type_object.tp_dealloc = (destructor) _t_iterator<U>::dealloc;
509             type_object.tp_flags = Py_TPFLAGS_DEFAULT;
510             type_object.tp_doc = "JArrayIterator<T> wrapper type";
511             type_object.tp_iter = (getiterfunc) PyObject_SelfIter;
512             type_object.tp_iternext = (iternextfunc) _t_iterator<U>::iternext;
513         }
514     };
515
516     iterator_type iterator_type_object;
517
518     void install(char *name, char *type_name, char *iterator_name,
519                  PyObject *module)
520     {
521         type_object.tp_name = name;
522
523         if (PyType_Ready(&type_object) == 0)
524         {
525             Py_INCREF((PyObject *) &type_object);
526             PyDict_SetItemString(type_object.tp_dict, "class_",
527                                  make_descriptor(initializeClass<T>));
528             
529             PyModule_AddObject(module, name, (PyObject *) &type_object);
530         }
531
532         U::format = PyString_FromFormat("JArray<%s>%%s", type_name);
533         iterator_type_object.install(iterator_name, module);
534     }
535
536     static PyObject *_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
537     {
538         U *self = (U *) type->tp_alloc(type, 0);
539
540         if (self)
541             self->array = JArray<T>((jobject) NULL);
542
543         return (PyObject *) self;
544     }
545
546     jarray_type()
547     {
548         memset(&seq_methods, 0, sizeof(seq_methods));
549         memset(&type_object, 0, sizeof(type_object));
550
551         static PyMethodDef methods[] = {
552             { "cast_",
553               (PyCFunction) (PyObject *(*)(PyTypeObject *,
554                                            PyObject *, PyObject *))
555               cast_<T>,
556               METH_VARARGS | METH_CLASS, NULL },
557             { "instance_",
558               (PyCFunction) (PyObject *(*)(PyTypeObject *,
559                                            PyObject *, PyObject *))
560               instance_<T>,
561               METH_VARARGS | METH_CLASS, NULL },
562             { "assignable_",
563               (PyCFunction) (PyObject *(*)(PyTypeObject *,
564                                            PyObject *, PyObject *))
565               assignable_<T>,
566               METH_VARARGS | METH_CLASS, NULL },
567             { NULL, NULL, 0, NULL }
568         };
569
570         seq_methods.sq_length =
571             (lenfunc) (Py_ssize_t (*)(U *)) seq_length<U>;
572         seq_methods.sq_concat =
573             (binaryfunc) (PyObject *(*)(U *, PyObject *)) seq_concat<U>;
574         seq_methods.sq_repeat =
575             (ssizeargfunc) (PyObject *(*)(U *, Py_ssize_t)) seq_repeat<U>;
576         seq_methods.sq_item =
577             (ssizeargfunc) (PyObject *(*)(U *, Py_ssize_t)) seq_get<U>;
578         seq_methods.sq_slice =
579             (ssizessizeargfunc) (PyObject *(*)(U *, Py_ssize_t, Py_ssize_t))
580             seq_getslice<U>;
581         seq_methods.sq_ass_item =
582             (ssizeobjargproc) (int (*)(U *, Py_ssize_t, PyObject *)) seq_set<U>;
583         seq_methods.sq_ass_slice =
584             (ssizessizeobjargproc) (int (*)(U *, Py_ssize_t, Py_ssize_t,
585                                             PyObject *)) seq_setslice<U>;
586         seq_methods.sq_contains =
587             (objobjproc) (int (*)(U *, PyObject *)) seq_contains<U>;
588         seq_methods.sq_inplace_concat = NULL;
589         seq_methods.sq_inplace_repeat = NULL;
590
591         type_object.ob_refcnt = 1;
592         type_object.tp_basicsize = sizeof(U);
593         type_object.tp_dealloc = (destructor) (void (*)(U *)) dealloc<T,U>;
594         type_object.tp_repr = (reprfunc) (PyObject *(*)(U *)) repr<U>;
595         type_object.tp_as_sequence = &seq_methods;
596         type_object.tp_str = (reprfunc) (PyObject *(*)(U *)) str<U>;
597         type_object.tp_flags = Py_TPFLAGS_DEFAULT;
598         type_object.tp_doc = "JArray<T> wrapper type";
599         type_object.tp_richcompare =
600             (richcmpfunc) (PyObject *(*)(U *, PyObject *, int)) richcompare<U>;
601         type_object.tp_iter = (getiterfunc) (PyObject *(*)(U *)) iter<U>;
602         type_object.tp_methods = methods;
603         type_object.tp_base = &PY_TYPE(Object);
604         type_object.tp_init =
605             (initproc) (int (*)(U *, PyObject *, PyObject *)) init<T,U>;
606         type_object.tp_new = (newfunc) _new;
607     }
608 };
609
610 template<typename T> class _t_jobjectarray : public _t_JArray<T> {
611 public:
612     PyObject *(*wrapfn)(const T&);
613 };
614
615 template<> PyObject *get(_t_jobjectarray<jobject> *self, Py_ssize_t n)
616 {
617     return self->array.get(n, self->wrapfn);
618 }
619
620 template<> PyObject *toSequence(_t_jobjectarray<jobject> *self)
621 {
622     return self->array.toSequence(self->wrapfn);
623 }
624
625 template<> PyObject *toSequence(_t_jobjectarray<jobject> *self,
626                                 Py_ssize_t lo, Py_ssize_t hi)
627 {
628     return self->array.toSequence(lo, hi, self->wrapfn);
629 }
630
631 template<> int init< jobject,_t_jobjectarray<jobject> >(_t_jobjectarray<jobject> *self, PyObject *args, PyObject *kwds)
632 {
633     PyObject *obj, *clsObj = NULL;
634     PyObject *(*wrapfn)(const jobject &) = NULL;
635     jclass cls;
636
637     if (!PyArg_ParseTuple(args, "O|O", &obj, &clsObj))
638         return -1;
639
640     if (clsObj == NULL)
641         cls = env->findClass("java/lang/Object");
642     else if (PyObject_TypeCheck(clsObj, &PY_TYPE(Class)))
643         cls = (jclass) ((t_Class *) clsObj)->object.this$;
644     else if (PyType_Check(clsObj))
645     {
646         if (PyType_IsSubtype((PyTypeObject *) clsObj, &PY_TYPE(JObject)))
647         {
648             PyObject *cobj = PyObject_GetAttrString(clsObj, "wrapfn_");
649
650             if (cobj == NULL)
651                 PyErr_Clear();
652             else
653             {
654                 wrapfn = (PyObject *(*)(const jobject &))
655                     PyCObject_AsVoidPtr(cobj);
656                 Py_DECREF(cobj);
657             }
658
659             clsObj = PyObject_GetAttrString(clsObj, "class_");
660             if (clsObj == NULL)
661                 return -1;
662
663             cls = (jclass) ((t_Class *) clsObj)->object.this$;
664             Py_DECREF(clsObj);
665         }
666         else
667         {
668             PyErr_SetObject(PyExc_ValueError, clsObj);
669             return -1;
670         }
671     }
672     else
673     {
674         PyErr_SetObject(PyExc_TypeError, clsObj);
675         return -1;
676     }
677
678     if (PySequence_Check(obj))
679     {
680         self->array = JArray<jobject>(cls, obj);
681         if (PyErr_Occurred())
682             return -1;
683     }
684     else if (PyGen_Check(obj))
685     {
686         PyObject *tuple =
687             PyObject_CallFunctionObjArgs((PyObject *) &PyTuple_Type, obj, NULL);
688
689         if (!tuple)
690             return -1;
691
692         self->array = JArray<jobject>(cls, tuple);
693         Py_DECREF(tuple);
694         if (PyErr_Occurred())
695             return -1;
696     }
697     else if (PyInt_Check(obj))
698     {
699         int n = PyInt_AsLong(obj);
700
701         if (n < 0)
702         {
703             PyErr_SetObject(PyExc_ValueError, obj);
704             return -1;
705         }
706
707         self->array = JArray<jobject>(cls, n);
708     }
709     else
710     {
711         PyErr_SetObject(PyExc_TypeError, obj);
712         return -1;
713     }
714
715     self->wrapfn = wrapfn;
716
717     return 0;
718 }
719
720 template<> jclass initializeClass<jobject>(void)
721 {
722     jclass cls = env->findClass("java/lang/Object");
723     return env->get_vm_env()->GetObjectClass(JArray<jobject>(cls, (Py_ssize_t) 0).this$);
724 }
725
726 template<> PyObject *cast_<jobject>(PyTypeObject *type,
727                                     PyObject *args, PyObject *kwds)
728 {
729     PyObject *arg, *clsArg = NULL;
730     PyObject *(*wrapfn)(const jobject&) = NULL;
731     jclass elementCls;
732
733     if (!PyArg_ParseTuple(args, "O|O", &arg, &clsArg))
734         return NULL;
735
736     if (!PyObject_TypeCheck(arg, &PY_TYPE(Object)))
737     {
738         PyErr_SetObject(PyExc_TypeError, arg);
739         return NULL;
740     }
741
742     Class argCls = ((t_Object *) arg)->object.getClass();
743
744     if (!argCls.isArray())
745     {
746         PyErr_SetObject(PyExc_TypeError, arg);
747         return NULL;
748     }
749
750     if (clsArg != NULL)
751     {
752         if (!PyType_Check(clsArg))
753         {
754             PyErr_SetObject(PyExc_TypeError, clsArg);
755             return NULL;
756         }
757         else if (!PyType_IsSubtype((PyTypeObject *) clsArg, &PY_TYPE(JObject)))
758         {
759             PyErr_SetObject(PyExc_ValueError, clsArg);
760             return NULL;
761         }
762
763         PyObject *cobj = PyObject_GetAttrString(clsArg, "wrapfn_");
764
765         if (cobj == NULL)
766             PyErr_Clear();
767         else
768         {
769             wrapfn = (PyObject *(*)(const jobject &)) PyCObject_AsVoidPtr(cobj);
770             Py_DECREF(cobj);
771         }
772
773         clsArg = PyObject_GetAttrString(clsArg, "class_");
774         if (clsArg == NULL)
775             return NULL;
776
777         elementCls = (jclass) ((t_Class *) clsArg)->object.this$;
778         Py_DECREF(clsArg);
779     }
780     else
781         elementCls = env->findClass("java/lang/Object");
782
783     JNIEnv *vm_env = env->get_vm_env();
784     jobjectArray array = vm_env->NewObjectArray(0, elementCls, NULL);
785     Class arrayCls(vm_env->GetObjectClass((jobject) array));
786
787     if (!arrayCls.isAssignableFrom(argCls))
788     {
789         PyErr_SetObject(PyExc_TypeError, arg);
790         return NULL;
791     }
792
793     return JArray<jobject>(((t_JObject *) arg)->object.this$).wrap(wrapfn);
794 }
795
796 template<> PyObject *instance_<jobject>(PyTypeObject *type,
797                                         PyObject *args, PyObject *kwds)
798 {
799     PyObject *arg, *clsArg = NULL;
800     jclass elementCls;
801
802     if (!PyArg_ParseTuple(args, "O|O", &arg, &clsArg))
803         return NULL;
804
805     if (!PyObject_TypeCheck(arg, &PY_TYPE(Object)))
806         Py_RETURN_FALSE;
807
808     Class argCls = ((t_Object *) arg)->object.getClass();
809
810     if (!argCls.isArray())
811         Py_RETURN_FALSE;
812
813     if (clsArg != NULL)
814     {
815         if (!PyType_Check(clsArg))
816         {
817             PyErr_SetObject(PyExc_TypeError, clsArg);
818             return NULL;
819         }
820         else if (!PyType_IsSubtype((PyTypeObject *) clsArg, &PY_TYPE(JObject)))
821         {
822             PyErr_SetObject(PyExc_ValueError, clsArg);
823             return NULL;
824         }
825
826         clsArg = PyObject_GetAttrString(clsArg, "class_");
827         if (clsArg == NULL)
828             return NULL;
829
830         elementCls = (jclass) ((t_Class *) clsArg)->object.this$;
831         Py_DECREF(clsArg);
832     }
833     else
834         elementCls = env->findClass("java/lang/Object");
835
836     JNIEnv *vm_env = env->get_vm_env();
837     jobjectArray array = vm_env->NewObjectArray(0, elementCls, NULL);
838     Class arrayCls(vm_env->GetObjectClass((jobject) array));
839
840     if (!arrayCls.isAssignableFrom(argCls))
841         Py_RETURN_FALSE;
842
843     Py_RETURN_TRUE;
844 }
845
846 template<> PyObject *assignable_<jobject>(PyTypeObject *type,
847                                           PyObject *args, PyObject *kwds)
848 {
849     PyObject *arg, *clsArg = NULL;
850     jclass elementCls;
851
852     if (!PyArg_ParseTuple(args, "O|O", &arg, &clsArg))
853         return NULL;
854
855     if (!PyObject_TypeCheck(arg, &PY_TYPE(Object)))
856         Py_RETURN_FALSE;
857
858     Class argCls = ((t_Object *) arg)->object.getClass();
859
860     if (!argCls.isArray())
861         Py_RETURN_FALSE;
862
863     if (clsArg != NULL)
864     {
865         if (!PyType_Check(clsArg))
866         {
867             PyErr_SetObject(PyExc_TypeError, clsArg);
868             return NULL;
869         }
870         else if (!PyType_IsSubtype((PyTypeObject *) clsArg, &PY_TYPE(JObject)))
871         {
872             PyErr_SetObject(PyExc_ValueError, clsArg);
873             return NULL;
874         }
875
876         clsArg = PyObject_GetAttrString(clsArg, "class_");
877         if (clsArg == NULL)
878             return NULL;
879
880         elementCls = (jclass) ((t_Class *) clsArg)->object.this$;
881         Py_DECREF(clsArg);
882     }
883     else
884         elementCls = env->findClass("java/lang/Object");
885
886     JNIEnv *vm_env = env->get_vm_env();
887     jobjectArray array = vm_env->NewObjectArray(0, elementCls, NULL);
888     Class arrayCls(vm_env->GetObjectClass((jobject) array));
889
890     if (!argCls.isAssignableFrom(arrayCls))
891         Py_RETURN_FALSE;
892
893     Py_RETURN_TRUE;
894 }
895
896
897 template<typename T> PyTypeObject *_t_iterator<T>::JArrayIterator;
898 template<typename T> PyObject *_t_JArray<T>::format;
899
900 static jarray_type< jobject, _t_jobjectarray<jobject> > jarray_jobject;
901
902 static jarray_type<jstring> jarray_jstring;
903 static jarray_type<jboolean> jarray_jboolean;
904 static jarray_type<jbyte> jarray_jbyte;
905 static jarray_type<jchar> jarray_jchar;
906 static jarray_type<jdouble> jarray_jdouble;
907 static jarray_type<jfloat> jarray_jfloat;
908 static jarray_type<jint> jarray_jint;
909 static jarray_type<jlong> jarray_jlong;
910 static jarray_type<jshort> jarray_jshort;
911
912
913 PyObject *JArray<jobject>::wrap(PyObject *(*wrapfn)(const jobject&))
914 {
915     if (this$ != NULL)
916     {
917         _t_jobjectarray<jobject> *obj =
918             PyObject_New(_t_jobjectarray<jobject>, &jarray_jobject.type_object);
919
920         memset(&(obj->array), 0, sizeof(JArray<jobject>));
921         obj->array = *this;
922         obj->wrapfn = wrapfn;
923
924         return (PyObject *) obj;
925     }
926
927     Py_RETURN_NONE;
928 }
929
930 PyObject *JArray<jstring>::wrap() const
931 {
932     if (this$ != NULL)
933     {
934         _t_JArray<jstring> *obj =
935             PyObject_New(_t_JArray<jstring>, &jarray_jstring.type_object);
936
937         memset(&(obj->array), 0, sizeof(JArray<jstring>));
938         obj->array = *this;
939
940         return (PyObject *) obj;
941     }
942
943     Py_RETURN_NONE;
944 }
945
946 PyObject *JArray<jboolean>::wrap() const
947 {
948     if (this$ != NULL)
949     {
950         _t_JArray<jboolean> *obj =
951             PyObject_New(_t_JArray<jboolean>, &jarray_jboolean.type_object);
952
953         memset(&(obj->array), 0, sizeof(JArray<jboolean>));
954         obj->array = *this;
955
956         return (PyObject *) obj;
957     }
958
959     Py_RETURN_NONE;
960 }
961
962 PyObject *JArray<jbyte>::wrap() const
963 {
964     if (this$ != NULL)
965     {
966         _t_JArray<jbyte> *obj =
967             PyObject_New(_t_JArray<jbyte>, &jarray_jbyte.type_object);
968
969         memset(&(obj->array), 0, sizeof(JArray<jbyte>));
970         obj->array = *this;
971
972         return (PyObject *) obj;
973     }
974
975     Py_RETURN_NONE;
976 }
977
978 PyObject *JArray<jchar>::wrap() const
979 {
980     if (this$ != NULL)
981     {
982         _t_JArray<jchar> *obj =
983             PyObject_New(_t_JArray<jchar>, &jarray_jchar.type_object);
984
985         memset(&(obj->array), 0, sizeof(JArray<jchar>));
986         obj->array = *this;
987
988         return (PyObject *) obj;
989     }
990
991     Py_RETURN_NONE;
992 }
993
994 PyObject *JArray<jdouble>::wrap() const
995 {
996     if (this$ != NULL)
997     {
998         _t_JArray<jdouble> *obj =
999             PyObject_New(_t_JArray<jdouble>, &jarray_jdouble.type_object);
1000
1001         memset(&(obj->array), 0, sizeof(JArray<jdouble>));
1002         obj->array = *this;
1003
1004         return (PyObject *) obj;
1005     }
1006
1007     Py_RETURN_NONE;
1008 }
1009
1010 PyObject *JArray<jfloat>::wrap() const
1011 {
1012     if (this$ != NULL)
1013     {
1014         _t_JArray<jfloat> *obj =
1015             PyObject_New(_t_JArray<jfloat>, &jarray_jfloat.type_object);
1016
1017         memset(&(obj->array), 0, sizeof(JArray<jfloat>));
1018         obj->array = *this;
1019
1020         return (PyObject *) obj;
1021     }
1022
1023     Py_RETURN_NONE;
1024 }
1025
1026 PyObject *JArray<jint>::wrap() const
1027 {
1028     if (this$ != NULL)
1029     {
1030         _t_JArray<jint> *obj =
1031             PyObject_New(_t_JArray<jint>, &jarray_jint.type_object);
1032
1033         memset(&(obj->array), 0, sizeof(JArray<jint>));
1034         obj->array = *this;
1035
1036         return (PyObject *) obj;
1037     }
1038
1039     Py_RETURN_NONE;
1040 }
1041
1042 PyObject *JArray<jlong>::wrap() const
1043 {
1044     if (this$ != NULL)
1045     {
1046         _t_JArray<jlong> *obj =
1047             PyObject_New(_t_JArray<jlong>, &jarray_jlong.type_object);
1048
1049         memset(&(obj->array), 0, sizeof(JArray<jlong>));
1050         obj->array = *this;
1051
1052         return (PyObject *) obj;
1053     }
1054
1055     Py_RETURN_NONE;
1056 }
1057
1058 PyObject *JArray<jshort>::wrap() const
1059 {
1060     if (this$ != NULL)
1061     {
1062         _t_JArray<jshort> *obj =
1063             PyObject_New(_t_JArray<jshort>, &jarray_jshort.type_object);
1064
1065         memset(&(obj->array), 0, sizeof(JArray<jshort>));
1066         obj->array = *this;
1067
1068         return (PyObject *) obj;
1069     }
1070
1071     Py_RETURN_NONE;
1072 }
1073
1074 PyObject *JArray_Type(PyObject *self, PyObject *arg)
1075 {
1076     PyObject *type_name = NULL, *type;
1077     char const *name = NULL;
1078
1079     if (PyType_Check(arg))
1080     {
1081         type_name = PyObject_GetAttrString(arg, "__name__");
1082         if (!type_name)
1083             return NULL;
1084     }
1085     else if (PyString_Check(arg))
1086     {
1087         type_name = arg;
1088         Py_INCREF(type_name);
1089     }
1090     else if (PyFloat_Check(arg))
1091     {
1092         type_name = NULL;
1093         name = "double";
1094     }
1095     else
1096     {
1097         PyObject *arg_type = (PyObject *) arg->ob_type;
1098
1099         type_name = PyObject_GetAttrString(arg_type, "__name__");
1100         if (!type_name)
1101             return NULL;
1102     }
1103
1104     if (type_name != NULL)
1105     {
1106         name = PyString_AsString(type_name);
1107         if (!name)
1108         {
1109             Py_DECREF(type_name);
1110             return NULL;
1111         }
1112     }
1113
1114     if (!strcmp(name, "object"))
1115         type = (PyObject *) &jarray_jobject.type_object;
1116     else if (!strcmp(name, "string"))
1117         type = (PyObject *) &jarray_jstring.type_object;
1118     else if (!strcmp(name, "bool"))
1119         type = (PyObject *) &jarray_jboolean.type_object;
1120     else if (!strcmp(name, "byte"))
1121         type = (PyObject *) &jarray_jbyte.type_object;
1122     else if (!strcmp(name, "char"))
1123         type = (PyObject *) &jarray_jchar.type_object;
1124     else if (!strcmp(name, "double"))
1125         type = (PyObject *) &jarray_jdouble.type_object;
1126     else if (!strcmp(name, "float"))
1127         type = (PyObject *) &jarray_jfloat.type_object;
1128     else if (!strcmp(name, "int"))
1129         type = (PyObject *) &jarray_jint.type_object;
1130     else if (!strcmp(name, "long"))
1131         type = (PyObject *) &jarray_jlong.type_object;
1132     else if (!strcmp(name, "short"))
1133         type = (PyObject *) &jarray_jshort.type_object;
1134     else
1135     {
1136         PyErr_SetObject(PyExc_ValueError, arg);
1137         Py_XDECREF(type_name);
1138
1139         return NULL;
1140     }
1141
1142     Py_INCREF(type);
1143     Py_XDECREF(type_name);
1144
1145     return type;
1146 }
1147
1148 static PyObject *t_JArray_jbyte__get_string_(t_JArray<jbyte> *self, void *data)
1149 {
1150     return self->array.to_string_();
1151 }
1152
1153 static PyGetSetDef t_JArray_jbyte__fields[] = {
1154     { "string_", (getter) t_JArray_jbyte__get_string_, NULL, "", NULL },
1155     { NULL, NULL, NULL, NULL, NULL }
1156 };
1157
1158
1159 PyTypeObject *PY_TYPE(JArrayObject);
1160 PyTypeObject *PY_TYPE(JArrayString);
1161 PyTypeObject *PY_TYPE(JArrayBool);
1162 PyTypeObject *PY_TYPE(JArrayByte);
1163 PyTypeObject *PY_TYPE(JArrayChar);
1164 PyTypeObject *PY_TYPE(JArrayDouble);
1165 PyTypeObject *PY_TYPE(JArrayFloat);
1166 PyTypeObject *PY_TYPE(JArrayInt);
1167 PyTypeObject *PY_TYPE(JArrayLong);
1168 PyTypeObject *PY_TYPE(JArrayShort);
1169
1170
1171 void _install_jarray(PyObject *module)
1172 {
1173     jarray_jobject.install("JArray_object", "object",
1174                             "__JArray_object_iterator", module);
1175     PY_TYPE(JArrayObject) = &jarray_jobject.type_object;
1176
1177     jarray_jstring.install("JArray_string", "string",
1178                             "__JArray_string_iterator", module);
1179     PY_TYPE(JArrayString) = &jarray_jstring.type_object;
1180
1181     jarray_jboolean.install("JArray_bool", "bool",
1182                             "__JArray_bool_iterator", module);
1183     PY_TYPE(JArrayBool) = &jarray_jboolean.type_object;
1184
1185     jarray_jbyte.type_object.tp_getset = t_JArray_jbyte__fields;
1186     jarray_jbyte.install("JArray_byte", "byte",
1187                          "__JArray_byte_iterator", module);
1188     PY_TYPE(JArrayByte) = &jarray_jbyte.type_object;
1189
1190     jarray_jchar.install("JArray_char", "char",
1191                          "__JArray_char_iterator", module);
1192     PY_TYPE(JArrayChar) = &jarray_jchar.type_object;
1193
1194     jarray_jdouble.install("JArray_double", "double",
1195                            "__JArray_double_iterator", module);
1196     PY_TYPE(JArrayDouble) = &jarray_jdouble.type_object;
1197
1198     jarray_jfloat.install("JArray_float", "float",
1199                           "__JArray_float_iterator", module);
1200     PY_TYPE(JArrayFloat) = &jarray_jfloat.type_object;
1201
1202     jarray_jint.install("JArray_int", "int",
1203                         "__JArray_int_iterator", module);
1204     PY_TYPE(JArrayInt) = &jarray_jint.type_object;
1205
1206     jarray_jlong.install("JArray_long", "long",
1207                          "__JArray_long_iterator", module);
1208     PY_TYPE(JArrayLong) = &jarray_jlong.type_object;
1209
1210     jarray_jshort.install("JArray_short", "short",
1211                           "__JArray_short_iterator", module);
1212     PY_TYPE(JArrayShort) = &jarray_jshort.type_object;
1213 }
1214
1215 #endif /* PYTHON */