PyLucene 3.4.0-1 import
[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, int 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, int lo, int 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     int 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     int 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 (int 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>(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, int 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, int lo, int hi)
626 {
627     return self->array.toSequence(lo, hi, self->wrapfn);
628 }
629
630 template<> int init< jobject,_t_jobjectarray<jobject> >(_t_jobjectarray<jobject> *self, PyObject *args, PyObject *kwds)
631 {
632     PyObject *obj, *clsObj = NULL;
633     PyObject *(*wrapfn)(const jobject &) = NULL;
634     jclass cls;
635
636     if (!PyArg_ParseTuple(args, "O|O", &obj, &clsObj))
637         return -1;
638
639     if (clsObj == NULL)
640         cls = env->findClass("java/lang/Object");
641     else if (PyObject_TypeCheck(clsObj, &PY_TYPE(Class)))
642         cls = (jclass) ((t_Class *) clsObj)->object.this$;
643     else if (PyType_Check(clsObj))
644     {
645         if (PyType_IsSubtype((PyTypeObject *) clsObj, &PY_TYPE(JObject)))
646         {
647             PyObject *cobj = PyObject_GetAttrString(clsObj, "wrapfn_");
648
649             if (cobj == NULL)
650                 PyErr_Clear();
651             else
652             {
653                 wrapfn = (PyObject *(*)(const jobject &))
654                     PyCObject_AsVoidPtr(cobj);
655                 Py_DECREF(cobj);
656             }
657
658             clsObj = PyObject_GetAttrString(clsObj, "class_");
659             if (clsObj == NULL)
660                 return -1;
661
662             cls = (jclass) ((t_Class *) clsObj)->object.this$;
663             Py_DECREF(clsObj);
664         }
665         else
666         {
667             PyErr_SetObject(PyExc_ValueError, clsObj);
668             return -1;
669         }
670     }
671     else
672     {
673         PyErr_SetObject(PyExc_TypeError, clsObj);
674         return -1;
675     }
676
677     if (PySequence_Check(obj))
678     {
679         self->array = JArray<jobject>(cls, obj);
680         if (PyErr_Occurred())
681             return -1;
682     }
683     else if (PyGen_Check(obj))
684     {
685         PyObject *tuple =
686             PyObject_CallFunctionObjArgs((PyObject *) &PyTuple_Type, obj, NULL);
687
688         if (!tuple)
689             return -1;
690
691         self->array = JArray<jobject>(cls, tuple);
692         Py_DECREF(tuple);
693         if (PyErr_Occurred())
694             return -1;
695     }
696     else if (PyInt_Check(obj))
697     {
698         int n = PyInt_AsLong(obj);
699
700         if (n < 0)
701         {
702             PyErr_SetObject(PyExc_ValueError, obj);
703             return -1;
704         }
705
706         self->array = JArray<jobject>(cls, n);
707     }
708     else
709     {
710         PyErr_SetObject(PyExc_TypeError, obj);
711         return -1;
712     }
713
714     self->wrapfn = wrapfn;
715
716     return 0;
717 }
718
719 template<> jclass initializeClass<jobject>(void)
720 {
721     jclass cls = env->findClass("java/lang/Object");
722     return env->get_vm_env()->GetObjectClass(JArray<jobject>(cls, 0).this$);
723 }
724
725 template<> PyObject *cast_<jobject>(PyTypeObject *type,
726                                     PyObject *args, PyObject *kwds)
727 {
728     PyObject *arg, *clsArg = NULL;
729     PyObject *(*wrapfn)(const jobject&) = NULL;
730     jclass elementCls;
731
732     if (!PyArg_ParseTuple(args, "O|O", &arg, &clsArg))
733         return NULL;
734
735     if (!PyObject_TypeCheck(arg, &PY_TYPE(Object)))
736     {
737         PyErr_SetObject(PyExc_TypeError, arg);
738         return NULL;
739     }
740
741     Class argCls = ((t_Object *) arg)->object.getClass();
742
743     if (!argCls.isArray())
744     {
745         PyErr_SetObject(PyExc_TypeError, arg);
746         return NULL;
747     }
748
749     if (clsArg != NULL)
750     {
751         if (!PyType_Check(clsArg))
752         {
753             PyErr_SetObject(PyExc_TypeError, clsArg);
754             return NULL;
755         }
756         else if (!PyType_IsSubtype((PyTypeObject *) clsArg, &PY_TYPE(JObject)))
757         {
758             PyErr_SetObject(PyExc_ValueError, clsArg);
759             return NULL;
760         }
761
762         PyObject *cobj = PyObject_GetAttrString(clsArg, "wrapfn_");
763
764         if (cobj == NULL)
765             PyErr_Clear();
766         else
767         {
768             wrapfn = (PyObject *(*)(const jobject &)) PyCObject_AsVoidPtr(cobj);
769             Py_DECREF(cobj);
770         }
771
772         clsArg = PyObject_GetAttrString(clsArg, "class_");
773         if (clsArg == NULL)
774             return NULL;
775
776         elementCls = (jclass) ((t_Class *) clsArg)->object.this$;
777         Py_DECREF(clsArg);
778     }
779     else
780         elementCls = env->findClass("java/lang/Object");
781
782     JNIEnv *vm_env = env->get_vm_env();
783     jobjectArray array = vm_env->NewObjectArray(0, elementCls, NULL);
784     Class arrayCls(vm_env->GetObjectClass((jobject) array));
785
786     if (!arrayCls.isAssignableFrom(argCls))
787     {
788         PyErr_SetObject(PyExc_TypeError, arg);
789         return NULL;
790     }
791
792     return JArray<jobject>(((t_JObject *) arg)->object.this$).wrap(wrapfn);
793 }
794
795 template<> PyObject *instance_<jobject>(PyTypeObject *type,
796                                         PyObject *args, PyObject *kwds)
797 {
798     PyObject *arg, *clsArg = NULL;
799     jclass elementCls;
800
801     if (!PyArg_ParseTuple(args, "O|O", &arg, &clsArg))
802         return NULL;
803
804     if (!PyObject_TypeCheck(arg, &PY_TYPE(Object)))
805         Py_RETURN_FALSE;
806
807     Class argCls = ((t_Object *) arg)->object.getClass();
808
809     if (!argCls.isArray())
810         Py_RETURN_FALSE;
811
812     if (clsArg != NULL)
813     {
814         if (!PyType_Check(clsArg))
815         {
816             PyErr_SetObject(PyExc_TypeError, clsArg);
817             return NULL;
818         }
819         else if (!PyType_IsSubtype((PyTypeObject *) clsArg, &PY_TYPE(JObject)))
820         {
821             PyErr_SetObject(PyExc_ValueError, clsArg);
822             return NULL;
823         }
824
825         clsArg = PyObject_GetAttrString(clsArg, "class_");
826         if (clsArg == NULL)
827             return NULL;
828
829         elementCls = (jclass) ((t_Class *) clsArg)->object.this$;
830         Py_DECREF(clsArg);
831     }
832     else
833         elementCls = env->findClass("java/lang/Object");
834
835     JNIEnv *vm_env = env->get_vm_env();
836     jobjectArray array = vm_env->NewObjectArray(0, elementCls, NULL);
837     Class arrayCls(vm_env->GetObjectClass((jobject) array));
838
839     if (!arrayCls.isAssignableFrom(argCls))
840         Py_RETURN_FALSE;
841
842     Py_RETURN_TRUE;
843 }
844
845 template<> PyObject *assignable_<jobject>(PyTypeObject *type,
846                                           PyObject *args, PyObject *kwds)
847 {
848     PyObject *arg, *clsArg = NULL;
849     jclass elementCls;
850
851     if (!PyArg_ParseTuple(args, "O|O", &arg, &clsArg))
852         return NULL;
853
854     if (!PyObject_TypeCheck(arg, &PY_TYPE(Object)))
855         Py_RETURN_FALSE;
856
857     Class argCls = ((t_Object *) arg)->object.getClass();
858
859     if (!argCls.isArray())
860         Py_RETURN_FALSE;
861
862     if (clsArg != NULL)
863     {
864         if (!PyType_Check(clsArg))
865         {
866             PyErr_SetObject(PyExc_TypeError, clsArg);
867             return NULL;
868         }
869         else if (!PyType_IsSubtype((PyTypeObject *) clsArg, &PY_TYPE(JObject)))
870         {
871             PyErr_SetObject(PyExc_ValueError, clsArg);
872             return NULL;
873         }
874
875         clsArg = PyObject_GetAttrString(clsArg, "class_");
876         if (clsArg == NULL)
877             return NULL;
878
879         elementCls = (jclass) ((t_Class *) clsArg)->object.this$;
880         Py_DECREF(clsArg);
881     }
882     else
883         elementCls = env->findClass("java/lang/Object");
884
885     JNIEnv *vm_env = env->get_vm_env();
886     jobjectArray array = vm_env->NewObjectArray(0, elementCls, NULL);
887     Class arrayCls(vm_env->GetObjectClass((jobject) array));
888
889     if (!argCls.isAssignableFrom(arrayCls))
890         Py_RETURN_FALSE;
891
892     Py_RETURN_TRUE;
893 }
894
895
896 template<typename T> PyTypeObject *_t_iterator<T>::JArrayIterator;
897 template<typename T> PyObject *_t_JArray<T>::format;
898
899 static jarray_type< jobject, _t_jobjectarray<jobject> > jarray_jobject;
900
901 static jarray_type<jstring> jarray_jstring;
902 static jarray_type<jboolean> jarray_jboolean;
903 static jarray_type<jbyte> jarray_jbyte;
904 static jarray_type<jchar> jarray_jchar;
905 static jarray_type<jdouble> jarray_jdouble;
906 static jarray_type<jfloat> jarray_jfloat;
907 static jarray_type<jint> jarray_jint;
908 static jarray_type<jlong> jarray_jlong;
909 static jarray_type<jshort> jarray_jshort;
910
911
912 PyObject *JArray<jobject>::wrap(PyObject *(*wrapfn)(const jobject&))
913 {
914     if (this$ != NULL)
915     {
916         _t_jobjectarray<jobject> *obj =
917             PyObject_New(_t_jobjectarray<jobject>, &jarray_jobject.type_object);
918
919         memset(&(obj->array), 0, sizeof(JArray<jobject>));
920         obj->array = *this;
921         obj->wrapfn = wrapfn;
922
923         return (PyObject *) obj;
924     }
925
926     Py_RETURN_NONE;
927 }
928
929 PyObject *JArray<jstring>::wrap() const
930 {
931     if (this$ != NULL)
932     {
933         _t_JArray<jstring> *obj =
934             PyObject_New(_t_JArray<jstring>, &jarray_jstring.type_object);
935
936         memset(&(obj->array), 0, sizeof(JArray<jstring>));
937         obj->array = *this;
938
939         return (PyObject *) obj;
940     }
941
942     Py_RETURN_NONE;
943 }
944
945 PyObject *JArray<jboolean>::wrap() const
946 {
947     if (this$ != NULL)
948     {
949         _t_JArray<jboolean> *obj =
950             PyObject_New(_t_JArray<jboolean>, &jarray_jboolean.type_object);
951
952         memset(&(obj->array), 0, sizeof(JArray<jboolean>));
953         obj->array = *this;
954
955         return (PyObject *) obj;
956     }
957
958     Py_RETURN_NONE;
959 }
960
961 PyObject *JArray<jbyte>::wrap() const
962 {
963     if (this$ != NULL)
964     {
965         _t_JArray<jbyte> *obj =
966             PyObject_New(_t_JArray<jbyte>, &jarray_jbyte.type_object);
967
968         memset(&(obj->array), 0, sizeof(JArray<jbyte>));
969         obj->array = *this;
970
971         return (PyObject *) obj;
972     }
973
974     Py_RETURN_NONE;
975 }
976
977 PyObject *JArray<jchar>::wrap() const
978 {
979     if (this$ != NULL)
980     {
981         _t_JArray<jchar> *obj =
982             PyObject_New(_t_JArray<jchar>, &jarray_jchar.type_object);
983
984         memset(&(obj->array), 0, sizeof(JArray<jchar>));
985         obj->array = *this;
986
987         return (PyObject *) obj;
988     }
989
990     Py_RETURN_NONE;
991 }
992
993 PyObject *JArray<jdouble>::wrap() const
994 {
995     if (this$ != NULL)
996     {
997         _t_JArray<jdouble> *obj =
998             PyObject_New(_t_JArray<jdouble>, &jarray_jdouble.type_object);
999
1000         memset(&(obj->array), 0, sizeof(JArray<jdouble>));
1001         obj->array = *this;
1002
1003         return (PyObject *) obj;
1004     }
1005
1006     Py_RETURN_NONE;
1007 }
1008
1009 PyObject *JArray<jfloat>::wrap() const
1010 {
1011     if (this$ != NULL)
1012     {
1013         _t_JArray<jfloat> *obj =
1014             PyObject_New(_t_JArray<jfloat>, &jarray_jfloat.type_object);
1015
1016         memset(&(obj->array), 0, sizeof(JArray<jfloat>));
1017         obj->array = *this;
1018
1019         return (PyObject *) obj;
1020     }
1021
1022     Py_RETURN_NONE;
1023 }
1024
1025 PyObject *JArray<jint>::wrap() const
1026 {
1027     if (this$ != NULL)
1028     {
1029         _t_JArray<jint> *obj =
1030             PyObject_New(_t_JArray<jint>, &jarray_jint.type_object);
1031
1032         memset(&(obj->array), 0, sizeof(JArray<jint>));
1033         obj->array = *this;
1034
1035         return (PyObject *) obj;
1036     }
1037
1038     Py_RETURN_NONE;
1039 }
1040
1041 PyObject *JArray<jlong>::wrap() const
1042 {
1043     if (this$ != NULL)
1044     {
1045         _t_JArray<jlong> *obj =
1046             PyObject_New(_t_JArray<jlong>, &jarray_jlong.type_object);
1047
1048         memset(&(obj->array), 0, sizeof(JArray<jlong>));
1049         obj->array = *this;
1050
1051         return (PyObject *) obj;
1052     }
1053
1054     Py_RETURN_NONE;
1055 }
1056
1057 PyObject *JArray<jshort>::wrap() const
1058 {
1059     if (this$ != NULL)
1060     {
1061         _t_JArray<jshort> *obj =
1062             PyObject_New(_t_JArray<jshort>, &jarray_jshort.type_object);
1063
1064         memset(&(obj->array), 0, sizeof(JArray<jshort>));
1065         obj->array = *this;
1066
1067         return (PyObject *) obj;
1068     }
1069
1070     Py_RETURN_NONE;
1071 }
1072
1073 PyObject *JArray_Type(PyObject *self, PyObject *arg)
1074 {
1075     PyObject *type_name = NULL, *type;
1076     char const *name = NULL;
1077
1078     if (PyType_Check(arg))
1079     {
1080         type_name = PyObject_GetAttrString(arg, "__name__");
1081         if (!type_name)
1082             return NULL;
1083     }
1084     else if (PyString_Check(arg))
1085     {
1086         type_name = arg;
1087         Py_INCREF(type_name);
1088     }
1089     else if (PyFloat_Check(arg))
1090     {
1091         type_name = NULL;
1092         name = "double";
1093     }
1094     else
1095     {
1096         PyObject *arg_type = (PyObject *) arg->ob_type;
1097
1098         type_name = PyObject_GetAttrString(arg_type, "__name__");
1099         if (!type_name)
1100             return NULL;
1101     }
1102
1103     if (type_name != NULL)
1104     {
1105         name = PyString_AsString(type_name);
1106         Py_DECREF(type_name);
1107
1108         if (!name)
1109             return NULL;
1110     }
1111
1112     if (!strcmp(name, "object"))
1113         type = (PyObject *) &jarray_jobject.type_object;
1114     else if (!strcmp(name, "string"))
1115         type = (PyObject *) &jarray_jstring.type_object;
1116     else if (!strcmp(name, "bool"))
1117         type = (PyObject *) &jarray_jboolean.type_object;
1118     else if (!strcmp(name, "byte"))
1119         type = (PyObject *) &jarray_jbyte.type_object;
1120     else if (!strcmp(name, "char"))
1121         type = (PyObject *) &jarray_jchar.type_object;
1122     else if (!strcmp(name, "double"))
1123         type = (PyObject *) &jarray_jdouble.type_object;
1124     else if (!strcmp(name, "float"))
1125         type = (PyObject *) &jarray_jfloat.type_object;
1126     else if (!strcmp(name, "int"))
1127         type = (PyObject *) &jarray_jint.type_object;
1128     else if (!strcmp(name, "long"))
1129         type = (PyObject *) &jarray_jlong.type_object;
1130     else if (!strcmp(name, "short"))
1131         type = (PyObject *) &jarray_jshort.type_object;
1132     else
1133     {
1134         PyErr_SetObject(PyExc_ValueError, arg);
1135         return NULL;
1136     }
1137
1138     Py_INCREF(type);
1139     return type;
1140 }
1141
1142 static PyObject *t_JArray_jbyte__get_string_(t_JArray<jbyte> *self, void *data)
1143 {
1144     return self->array.to_string_();
1145 }
1146
1147 static PyGetSetDef t_JArray_jbyte__fields[] = {
1148     { "string_", (getter) t_JArray_jbyte__get_string_, NULL, "", NULL },
1149     { NULL, NULL, NULL, NULL, NULL }
1150 };
1151
1152
1153 PyTypeObject *PY_TYPE(JArrayObject);
1154 PyTypeObject *PY_TYPE(JArrayString);
1155 PyTypeObject *PY_TYPE(JArrayBool);
1156 PyTypeObject *PY_TYPE(JArrayByte);
1157 PyTypeObject *PY_TYPE(JArrayChar);
1158 PyTypeObject *PY_TYPE(JArrayDouble);
1159 PyTypeObject *PY_TYPE(JArrayFloat);
1160 PyTypeObject *PY_TYPE(JArrayInt);
1161 PyTypeObject *PY_TYPE(JArrayLong);
1162 PyTypeObject *PY_TYPE(JArrayShort);
1163
1164
1165 void _install_jarray(PyObject *module)
1166 {
1167     jarray_jobject.install("JArray_object", "object",
1168                             "__JArray_object_iterator", module);
1169     PY_TYPE(JArrayObject) = &jarray_jobject.type_object;
1170
1171     jarray_jstring.install("JArray_string", "string",
1172                             "__JArray_string_iterator", module);
1173     PY_TYPE(JArrayString) = &jarray_jstring.type_object;
1174
1175     jarray_jboolean.install("JArray_bool", "bool",
1176                             "__JArray_bool_iterator", module);
1177     PY_TYPE(JArrayBool) = &jarray_jboolean.type_object;
1178
1179     jarray_jbyte.type_object.tp_getset = t_JArray_jbyte__fields;
1180     jarray_jbyte.install("JArray_byte", "byte",
1181                          "__JArray_byte_iterator", module);
1182     PY_TYPE(JArrayByte) = &jarray_jbyte.type_object;
1183
1184     jarray_jchar.install("JArray_char", "char",
1185                          "__JArray_char_iterator", module);
1186     PY_TYPE(JArrayChar) = &jarray_jchar.type_object;
1187
1188     jarray_jdouble.install("JArray_double", "double",
1189                            "__JArray_double_iterator", module);
1190     PY_TYPE(JArrayDouble) = &jarray_jdouble.type_object;
1191
1192     jarray_jfloat.install("JArray_float", "float",
1193                           "__JArray_float_iterator", module);
1194     PY_TYPE(JArrayFloat) = &jarray_jfloat.type_object;
1195
1196     jarray_jint.install("JArray_int", "int",
1197                         "__JArray_int_iterator", module);
1198     PY_TYPE(JArrayInt) = &jarray_jint.type_object;
1199
1200     jarray_jlong.install("JArray_long", "long",
1201                          "__JArray_long_iterator", module);
1202     PY_TYPE(JArrayLong) = &jarray_jlong.type_object;
1203
1204     jarray_jshort.install("JArray_short", "short",
1205                           "__JArray_short_iterator", module);
1206     PY_TYPE(JArrayShort) = &jarray_jshort.type_object;
1207 }
1208
1209 #endif /* PYTHON */