PyLucene 3.4.0-1 import
[pylucene.git] / jcc / jcc / sources / JArray.h
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 #ifndef _JArray_H
16 #define _JArray_H
17
18 #ifdef PYTHON
19 #include <Python.h>
20 #include "macros.h"
21
22 extern jobjectArray fromPySequence(jclass cls, PyObject *sequence);
23 extern PyObject *PyErr_SetJavaError();
24
25 extern PyTypeObject *PY_TYPE(JArrayObject);
26 extern PyTypeObject *PY_TYPE(JArrayString);
27 extern PyTypeObject *PY_TYPE(JArrayBool);
28 extern PyTypeObject *PY_TYPE(JArrayByte);
29 extern PyTypeObject *PY_TYPE(JArrayChar);
30 extern PyTypeObject *PY_TYPE(JArrayDouble);
31 extern PyTypeObject *PY_TYPE(JArrayFloat);
32 extern PyTypeObject *PY_TYPE(JArrayInt);
33 extern PyTypeObject *PY_TYPE(JArrayLong);
34 extern PyTypeObject *PY_TYPE(JArrayShort);
35
36 #endif
37
38 #include "JCCEnv.h"
39 #include "java/lang/Object.h"
40
41
42 template<typename T> class JArray : public java::lang::Object {
43 public:
44     int length;
45
46     explicit JArray<T>(jobject obj) : java::lang::Object(obj) {
47         length = this$ ? env->getArrayLength((jobjectArray) this$) : 0;
48     }
49     JArray<T>(const JArray<T>& obj) : java::lang::Object(obj) {
50         length = obj.length;
51     }
52
53 #ifdef PYTHON
54     JArray<T>(PyObject *sequence) : java::lang::Object(fromPySequence(T::initializeClass(), sequence)) {
55         length = this$ ? env->getArrayLength((jobjectArray) this$) : 0;
56     }
57
58     JArray<T>(jclass cls, PyObject *sequence) : java::lang::Object(fromPySequence(cls, sequence)) {
59         length = this$ ? env->getArrayLength((jobjectArray) this$) : 0;
60     }
61
62     PyObject *toSequence(PyObject *(*wrapfn)(const T&))
63     {
64         if (this$ == NULL)
65             Py_RETURN_NONE;
66
67         PyObject *list = PyList_New(length);
68
69         for (int i = 0; i < length; i++)
70             PyList_SET_ITEM(list, i, (*wrapfn)((*this)[i]));
71
72         return list;
73     }
74
75     PyObject *get(int n, PyObject *(*wrapfn)(const T&))
76     {
77         if (this$ != NULL)
78         {
79             if (n < 0)
80                 n = length + n;
81
82             if (n >= 0 && n < length)
83                 return (*wrapfn)((*this)[n]);
84         }
85
86         PyErr_SetString(PyExc_IndexError, "index out of range");
87         return NULL;
88     }
89 #endif
90
91     T operator[](int n) {
92         return T(env->getObjectArrayElement((jobjectArray) this$, n));
93     }
94 };
95
96 template<> class JArray<jobject> : public java::lang::Object {
97   public:
98     int length;
99
100     JArray<jobject>(jclass cls, int n) : java::lang::Object(env->get_vm_env()->NewObjectArray(n, cls, NULL)) {
101         length = env->getArrayLength((jobjectArray) this$);
102     }
103
104     JArray<jobject>(jobject obj) : java::lang::Object(obj) {
105         length = this$ ? env->getArrayLength((jobjectArray) this$) : 0;
106     }
107
108     JArray<jobject>(const JArray& obj) : java::lang::Object(obj) {
109         length = obj.length;
110     }
111
112 #ifdef PYTHON
113     JArray<jobject>(jclass cls, PyObject *sequence) : java::lang::Object(fromPySequence(cls, sequence)) {
114         length = this$ ? env->getArrayLength((jobjectArray) this$) : 0;
115     }
116
117     PyObject *toSequence(PyObject *(*wrapfn)(const jobject&))
118     {
119         return toSequence(0, length, wrapfn);
120     }
121
122     PyObject *toSequence(int lo, int hi, PyObject *(*wrapfn)(const jobject&))
123     {
124         if (this$ == NULL)
125             Py_RETURN_NONE;
126
127         if (lo < 0) lo = length + lo;
128         if (lo < 0) lo = 0;
129         else if (lo > length) lo = length;
130         if (hi < 0) hi = length + hi;
131         if (hi < 0) hi = 0;
132         else if (hi > length) hi = length;
133         if (lo > hi) lo = hi;
134
135         PyObject *list = PyList_New(hi - lo);
136
137         if (!wrapfn)
138             wrapfn = java::lang::t_Object::wrap_jobject;
139
140         for (int i = lo; i < hi; i++) {
141             jobject jobj = env->getObjectArrayElement((jobjectArray) this$, i);
142             PyObject *obj = (*wrapfn)(jobj);
143
144             PyList_SET_ITEM(list, i - lo, obj);
145         }
146          
147         return list;
148     }
149
150     PyObject *get(int n, PyObject *(*wrapfn)(const jobject&))
151     {
152         if (this$ != NULL)
153         {
154             if (n < 0)
155                 n = length + n;
156
157             if (n >= 0 && n < length)
158             {
159                 if (!wrapfn)
160                     wrapfn = java::lang::t_Object::wrap_jobject;
161
162                 jobject jobj =
163                     env->getObjectArrayElement((jobjectArray) this$, n);
164
165                 return (*wrapfn)(jobj);
166             }
167         }
168
169         PyErr_SetString(PyExc_IndexError, "index out of range");
170         return NULL;
171     }
172
173     int set(int n, PyObject *obj)
174     {
175         if (this$ != NULL)
176         {
177             if (n < 0)
178                 n = length + n;
179
180             if (n >= 0 && n < length)
181             {
182                 if (!PyObject_TypeCheck(obj, &PY_TYPE(JObject)))
183                 {
184                     PyErr_SetObject(PyExc_TypeError, obj);
185                     return -1;
186                 }
187
188                 jobject jobj = ((t_JObject *) obj)->object.this$;
189
190                 try {
191                     env->setObjectArrayElement((jobjectArray) this$, n, jobj);
192                 } catch (int e) {
193                     switch (e) {
194                       case _EXC_JAVA:
195                         PyErr_SetJavaError();
196                         return -1;
197                       default:
198                         throw;
199                     }
200                 }
201
202                 return 0;
203             }
204         }
205
206         PyErr_SetString(PyExc_IndexError, "index out of range");
207         return -1;
208     }
209
210     PyObject *wrap(PyObject *(*wrapfn)(const jobject&));
211 #endif
212
213     jobject operator[](int n) {
214         return (jobject) env->getObjectArrayElement((jobjectArray) this$, n);
215     }
216 };
217
218 template<> class JArray<jstring> : public java::lang::Object {
219   public:
220     int length;
221
222     JArray<jstring>(jobject obj) : java::lang::Object(obj) {
223         length = this$ ? env->getArrayLength((jobjectArray) this$) : 0;
224     }
225
226     JArray<jstring>(const JArray& obj) : java::lang::Object(obj) {
227         length = obj.length;
228     }
229
230     JArray<jstring>(int n) : java::lang::Object(env->get_vm_env()->NewObjectArray(n, env->findClass("java/lang/String"), NULL)) {
231         length = env->getArrayLength((jobjectArray) this$);
232     }
233
234 #ifdef PYTHON
235     JArray<jstring>(PyObject *sequence) : java::lang::Object(env->get_vm_env()->NewObjectArray(PySequence_Length(sequence), env->findClass("java/lang/String"), NULL)) {
236         length = env->getArrayLength((jobjectArray) this$);
237
238         for (int i = 0; i < length; i++) {
239             PyObject *obj = PySequence_GetItem(sequence, i);
240
241             if (obj == NULL)
242                 break;
243
244             jstring str = env->fromPyString(obj);
245
246             Py_DECREF(obj);
247             if (PyErr_Occurred())
248                 break;
249
250             env->setObjectArrayElement((jobjectArray) this$, i, str);
251             env->get_vm_env()->DeleteLocalRef(str);
252         }
253     }
254
255     PyObject *toSequence()
256     {
257         return toSequence(0, length);
258     }
259
260     PyObject *toSequence(int lo, int hi)
261     {
262         if (this$ == NULL)
263             Py_RETURN_NONE;
264
265         if (lo < 0) lo = length + lo;
266         if (lo < 0) lo = 0;
267         else if (lo > length) lo = length;
268         if (hi < 0) hi = length + hi;
269         if (hi < 0) hi = 0;
270         else if (hi > length) hi = length;
271         if (lo > hi) lo = hi;
272
273         PyObject *list = PyList_New(hi - lo);
274
275         for (int i = lo; i < hi; i++) {
276             jstring str = (jstring)
277                 env->getObjectArrayElement((jobjectArray) this$, i);
278             PyObject *obj = env->fromJString(str, 1);
279
280             PyList_SET_ITEM(list, i - lo, obj);
281         }
282          
283         return list;
284     }
285
286     PyObject *get(int n)
287     {
288         if (this$ != NULL)
289         {
290             if (n < 0)
291                 n = length + n;
292
293             if (n >= 0 && n < length)
294             {
295                 jstring str = (jstring)
296                     env->getObjectArrayElement((jobjectArray) this$, n);
297                 PyObject *obj = env->fromJString(str, 1);
298
299                 return obj;
300             }
301         }
302
303         PyErr_SetString(PyExc_IndexError, "index out of range");
304         return NULL;
305     }
306
307     int set(int n, PyObject *obj)
308     {
309         if (this$ != NULL)
310         {
311             if (n < 0)
312                 n = length + n;
313
314             if (n >= 0 && n < length)
315             {
316                 jstring str = env->fromPyString(obj);
317
318                 if (PyErr_Occurred())
319                     return -1;
320
321                 env->setObjectArrayElement((jobjectArray) this$, n, str);
322                 return 0;
323             }
324         }
325
326         PyErr_SetString(PyExc_IndexError, "index out of range");
327         return -1;
328     }
329
330     PyObject *wrap() const;
331 #endif
332
333     jstring operator[](int n) {
334         return (jstring) env->getObjectArrayElement((jobjectArray) this$, n);
335     }
336 };
337
338 template<> class JArray<jboolean> : public java::lang::Object {
339   public:
340     int length;
341
342     class arrayElements {
343     private:
344         jboolean isCopy;
345         jbooleanArray array;
346         jboolean *elts;
347     public:
348         arrayElements(jbooleanArray array) {
349             this->array = array;
350             elts = env->get_vm_env()->GetBooleanArrayElements(array, &isCopy);
351         }
352         virtual ~arrayElements() {
353             env->get_vm_env()->ReleaseBooleanArrayElements(array, elts, 0);
354         }
355         operator jboolean *() {
356             return elts;
357         }
358     };
359
360     arrayElements elements() {
361         return arrayElements((jbooleanArray) this$);
362     }
363
364     JArray<jboolean>(jobject obj) : java::lang::Object(obj) {
365         length = this$ ? env->getArrayLength((jarray) this$) : 0;
366     }
367
368     JArray<jboolean>(const JArray& obj) : java::lang::Object(obj) {
369         length = obj.length;
370     }
371
372     JArray<jboolean>(int n) : java::lang::Object(env->get_vm_env()->NewBooleanArray(n)) {
373         length = env->getArrayLength((jarray) this$);
374     }
375
376 #ifdef PYTHON
377     JArray<jboolean>(PyObject *sequence) : java::lang::Object(env->get_vm_env()->NewBooleanArray(PySequence_Length(sequence))) {
378         length = env->getArrayLength((jarray) this$);
379         arrayElements elts = elements();
380         jboolean *buf = (jboolean *) elts;
381
382         for (int i = 0; i < length; i++) {
383             PyObject *obj = PySequence_GetItem(sequence, i);
384
385             if (!obj)
386                 break;
387
388             if (obj == Py_True || obj == Py_False)
389             {
390                 buf[i] = (jboolean) (obj == Py_True);
391                 Py_DECREF(obj);
392             }
393             else
394             {
395                 PyErr_SetObject(PyExc_TypeError, obj);
396                 Py_DECREF(obj);
397                 break;
398             }
399         }
400     }
401
402     PyObject *toSequence()
403     {
404         return toSequence(0, length);
405     }
406
407     PyObject *toSequence(int lo, int hi)
408     {
409         if (this$ == NULL)
410             Py_RETURN_NONE;
411
412         if (lo < 0) lo = length + lo;
413         if (lo < 0) lo = 0;
414         else if (lo > length) lo = length;
415         if (hi < 0) hi = length + hi;
416         if (hi < 0) hi = 0;
417         else if (hi > length) hi = length;
418         if (lo > hi) lo = hi;
419
420         PyObject *list = PyList_New(hi - lo);
421         arrayElements elts = elements();
422         jboolean *buf = (jboolean *) elts;
423
424         for (int i = lo; i < hi; i++) {
425             jboolean value = buf[i];
426             PyObject *obj = value ? Py_True : Py_False;
427
428             Py_INCREF(obj);
429             PyList_SET_ITEM(list, i - lo, obj);
430         }
431          
432         return list;
433     }
434
435     PyObject *get(int n)
436     {
437         if (this$ != NULL)
438         {
439             if (n < 0)
440                 n = length + n;
441
442             if (n >= 0 && n < length)
443                 Py_RETURN_BOOL(elements()[n]);
444         }
445
446         PyErr_SetString(PyExc_IndexError, "index out of range");
447         return NULL;
448     }
449
450     int set(int n, PyObject *obj)
451     {
452         if (this$ != NULL)
453         {
454             if (n < 0)
455                 n = length + n;
456
457             if (n >= 0 && n < length)
458             {
459                 elements()[n] = (jboolean) PyObject_IsTrue(obj);
460                 return 0;
461             }
462         }
463
464         PyErr_SetString(PyExc_IndexError, "index out of range");
465         return -1;
466     }
467
468     PyObject *wrap() const;
469 #endif
470
471     jboolean operator[](int n) {
472         JNIEnv *vm_env = env->get_vm_env();
473         jboolean isCopy = 0;
474         jboolean *elts = (jboolean *)
475             vm_env->GetPrimitiveArrayCritical((jarray) this$, &isCopy);
476         jboolean value = elts[n];
477
478         vm_env->ReleasePrimitiveArrayCritical((jarray) this$, elts, 0);
479
480         return value;
481     }
482 };
483
484 template<> class JArray<jbyte> : public java::lang::Object {
485   public:
486     int length;
487
488     class arrayElements {
489     private:
490         jboolean isCopy;
491         jbyteArray array;
492         jbyte *elts;
493     public:
494         arrayElements(jbyteArray array) {
495             this->array = array;
496             elts = env->get_vm_env()->GetByteArrayElements(array, &isCopy);
497         }
498         virtual ~arrayElements() {
499             env->get_vm_env()->ReleaseByteArrayElements(array, elts, 0);
500         }
501         operator jbyte *() {
502             return elts;
503         }
504     };
505
506     arrayElements elements() {
507         return arrayElements((jbyteArray) this$);
508     }
509
510     JArray<jbyte>(jobject obj) : java::lang::Object(obj) {
511         length = this$ ? env->getArrayLength((jarray) this$) : 0;
512     }
513
514     JArray<jbyte>(const JArray& obj) : java::lang::Object(obj) {
515         length = obj.length;
516     }
517
518     JArray<jbyte>(int n) : java::lang::Object(env->get_vm_env()->NewByteArray(n)) {
519         length = env->getArrayLength((jarray) this$);
520     }
521
522 #ifdef PYTHON
523     JArray<jbyte>(PyObject *sequence) : java::lang::Object(env->get_vm_env()->NewByteArray(PySequence_Length(sequence))) {
524         length = env->getArrayLength((jarray) this$);
525         arrayElements elts = elements();
526         jbyte *buf = (jbyte *) elts;
527
528         if (PyString_Check(sequence))
529             memcpy(buf, PyString_AS_STRING(sequence), length);
530         else
531             for (int i = 0; i < length; i++) {
532                 PyObject *obj = PySequence_GetItem(sequence, i);
533
534                 if (!obj)
535                     break;
536
537                 if (PyString_Check(obj) && (PyString_GET_SIZE(obj) == 1))
538                 {
539                     buf[i] = (jbyte) PyString_AS_STRING(obj)[0];
540                     Py_DECREF(obj);
541                 }
542                 else if (PyInt_CheckExact(obj))
543                 {
544                     buf[i] = (jbyte) PyInt_AS_LONG(obj);
545                     Py_DECREF(obj);
546                 }
547                 else
548                 {
549                     PyErr_SetObject(PyExc_TypeError, obj);
550                     Py_DECREF(obj);
551                     break;
552                 }
553             }
554     }
555
556     char getType()
557     {
558         return 'Z';
559     }
560
561     PyObject *toSequence()
562     {
563         return toSequence(0, length);
564     }
565
566     PyObject *toSequence(int lo, int hi)
567     {
568         if (this$ == NULL)
569             Py_RETURN_NONE;
570
571         if (lo < 0) lo = length + lo;
572         if (lo < 0) lo = 0;
573         else if (lo > length) lo = length;
574         if (hi < 0) hi = length + hi;
575         if (hi < 0) hi = 0;
576         else if (hi > length) hi = length;
577         if (lo > hi) lo = hi;
578
579         arrayElements elts = elements();
580         jbyte *buf = (jbyte *) elts;
581         PyObject *tuple = PyTuple_New(hi - lo);
582         
583         for (int i = 0; i < hi - lo; i++)
584             PyTuple_SET_ITEM(tuple, i, PyInt_FromLong(buf[lo + i]));
585
586         return tuple;
587     }
588
589     PyObject *to_string_()
590     {
591         if (this$ == NULL)
592             Py_RETURN_NONE;
593
594         arrayElements elts = elements();
595         jbyte *buf = (jbyte *) elts;
596
597         return PyString_FromStringAndSize((char *) buf, length);
598     }
599
600     PyObject *get(int n)
601     {
602         if (this$ != NULL)
603         {
604             if (n < 0)
605                 n = length + n;
606
607             if (n >= 0 && n < length)
608             {
609                 jbyte b = (*this)[n];
610                 return PyInt_FromLong(b);
611             }
612         }
613
614         PyErr_SetString(PyExc_IndexError, "index out of range");
615         return NULL;
616     }
617
618     int set(int n, PyObject *obj)
619     {
620         if (this$ != NULL)
621         {
622             if (n < 0)
623                 n = length + n;
624
625             if (n >= 0 && n < length)
626             {
627                 if (!PyInt_CheckExact(obj))
628                 {
629                     PyErr_SetObject(PyExc_TypeError, obj);
630                     return -1;
631                 }
632
633                 elements()[n] = (jbyte) PyInt_AS_LONG(obj);
634                 return 0;
635             }
636         }
637
638         PyErr_SetString(PyExc_IndexError, "index out of range");
639         return -1;
640     }
641
642     PyObject *wrap() const;
643 #endif
644
645     jbyte operator[](int n) {
646         JNIEnv *vm_env = env->get_vm_env();
647         jboolean isCopy = 0;
648         jbyte *elts = (jbyte *)
649             vm_env->GetPrimitiveArrayCritical((jarray) this$, &isCopy);
650         jbyte value = elts[n];
651
652         vm_env->ReleasePrimitiveArrayCritical((jarray) this$, elts, 0);
653
654         return value;
655     }
656 };
657
658 template<> class JArray<jchar> : public java::lang::Object {
659   public:
660     int length;
661
662     class arrayElements {
663     private:
664         jboolean isCopy;
665         jcharArray array;
666         jchar *elts;
667     public:
668         arrayElements(jcharArray array) {
669             this->array = array;
670             elts = env->get_vm_env()->GetCharArrayElements(array, &isCopy);
671         }
672         virtual ~arrayElements() {
673             env->get_vm_env()->ReleaseCharArrayElements(array, elts, 0);
674         }
675         operator jchar *() {
676             return elts;
677         }
678     };
679
680     arrayElements elements() {
681         return arrayElements((jcharArray) this$);
682     }
683
684     JArray<jchar>(jobject obj) : java::lang::Object(obj) {
685         length = this$ ? env->getArrayLength((jarray) this$) : 0;
686     }
687
688     JArray<jchar>(const JArray& obj) : java::lang::Object(obj) {
689         length = obj.length;
690     }
691
692     JArray<jchar>(int n) : java::lang::Object(env->get_vm_env()->NewCharArray(n)) {
693         length = env->getArrayLength((jarray) this$);
694     }
695
696 #ifdef PYTHON
697     JArray<jchar>(PyObject *sequence) : java::lang::Object(env->get_vm_env()->NewCharArray(PySequence_Length(sequence))) {
698         length = env->getArrayLength((jarray) this$);
699         arrayElements elts = elements();
700         jchar *buf = (jchar *) elts;
701
702         if (PyUnicode_Check(sequence))
703         {
704             if (sizeof(Py_UNICODE) == sizeof(jchar))
705                 memcpy(buf, PyUnicode_AS_UNICODE(sequence),
706                        length * sizeof(jchar));
707             else
708             {
709                 Py_UNICODE *pchars = PyUnicode_AS_UNICODE(sequence);
710                 for (int i = 0; i < length; i++)
711                     buf[i] = (jchar) pchars[i];
712             }
713         }
714         else
715             for (int i = 0; i < length; i++) {
716                 PyObject *obj = PySequence_GetItem(sequence, i);
717
718                 if (!obj)
719                     break;
720
721                 if (PyUnicode_Check(obj) && (PyUnicode_GET_SIZE(obj) == 1))
722                 {
723                     buf[i] = (jchar) PyUnicode_AS_UNICODE(obj)[0];
724                     Py_DECREF(obj);
725                 }
726                 else
727                 {
728                     PyErr_SetObject(PyExc_TypeError, obj);
729                     Py_DECREF(obj);
730                     break;
731                 }
732             }
733     }
734
735     PyObject *toSequence()
736     {
737         return toSequence(0, length);
738     }
739
740     PyObject *toSequence(int lo, int hi)
741     {
742         if (this$ == NULL)
743             Py_RETURN_NONE;
744
745         if (lo < 0) lo = length + lo;
746         if (lo < 0) lo = 0;
747         else if (lo > length) lo = length;
748         if (hi < 0) hi = length + hi;
749         if (hi < 0) hi = 0;
750         else if (hi > length) hi = length;
751         if (lo > hi) lo = hi;
752
753         arrayElements elts = elements();
754         jchar *buf = (jchar *) elts;
755
756         if (sizeof(Py_UNICODE) == sizeof(jchar))
757             return PyUnicode_FromUnicode((const Py_UNICODE *) buf + lo,
758                                          hi - lo);
759         else
760         {
761             PyObject *string = PyUnicode_FromUnicode(NULL, hi - lo);
762             Py_UNICODE *pchars = PyUnicode_AS_UNICODE(string);
763
764             for (int i = lo; i < hi; i++)
765                 pchars[i - lo] = (Py_UNICODE) buf[i];
766
767             return string;
768         }
769     }
770
771     PyObject *get(int n)
772     {
773         if (this$ != NULL)
774         {
775             if (n < 0)
776                 n = length + n;
777
778             if (n >= 0 && n < length)
779             {
780                 jchar c = (*this)[n];
781
782                 if (sizeof(Py_UNICODE) == sizeof(jchar))
783                     return PyUnicode_FromUnicode((const Py_UNICODE *) &c, 1);
784                 else
785                 {
786                     PyObject *string = PyUnicode_FromUnicode(NULL, 1);
787                     Py_UNICODE *pchars = PyUnicode_AS_UNICODE(string);
788
789                     pchars[0] = (Py_UNICODE) c;
790
791                     return string;
792                 }
793             }
794         }
795
796         PyErr_SetString(PyExc_IndexError, "index out of range");
797         return NULL;
798     }
799
800     int set(int n, PyObject *obj)
801     {
802         if (this$ != NULL)
803         {
804             if (n < 0)
805                 n = length + n;
806
807             if (n >= 0 && n < length)
808             {
809                 if (!PyUnicode_Check(obj))
810                 {
811                     PyErr_SetObject(PyExc_TypeError, obj);
812                     return -1;
813                 }
814                 if (PyUnicode_GET_SIZE(obj) != 1)
815                 {
816                     PyErr_SetObject(PyExc_ValueError, obj);
817                     return -1;
818                 }
819
820                 elements()[n] = (jchar) PyUnicode_AS_UNICODE(obj)[0];
821                 return 0;
822             }
823         }
824
825         PyErr_SetString(PyExc_IndexError, "index out of range");
826         return -1;
827     }
828
829     PyObject *wrap() const;
830 #endif
831
832     jchar operator[](int n) {
833         JNIEnv *vm_env = env->get_vm_env();
834         jboolean isCopy = 0;
835         jchar *elts = (jchar *)
836             vm_env->GetPrimitiveArrayCritical((jarray) this$, &isCopy);
837         jchar value = elts[n];
838
839         vm_env->ReleasePrimitiveArrayCritical((jarray) this$, elts, 0);
840
841         return value;
842     }
843 };
844
845 template<> class JArray<jdouble> : public java::lang::Object {
846   public:
847     int length;
848
849     class arrayElements {
850     private:
851         jboolean isCopy;
852         jdoubleArray array;
853         jdouble *elts;
854     public:
855         arrayElements(jdoubleArray array) {
856             this->array = array;
857             elts = env->get_vm_env()->GetDoubleArrayElements(array, &isCopy);
858         }
859         virtual ~arrayElements() {
860             env->get_vm_env()->ReleaseDoubleArrayElements(array, elts, 0);
861         }
862         operator jdouble *() {
863             return elts;
864         }
865     };
866
867     arrayElements elements() {
868         return arrayElements((jdoubleArray) this$);
869     }
870
871     JArray<jdouble>(jobject obj) : java::lang::Object(obj) {
872         length = this$ ? env->getArrayLength((jarray) this$) : 0;
873     }
874
875     JArray<jdouble>(const JArray& obj) : java::lang::Object(obj) {
876         length = obj.length;
877     }
878
879     JArray<jdouble>(int n) : java::lang::Object(env->get_vm_env()->NewDoubleArray(n)) {
880         length = env->getArrayLength((jarray) this$);
881     }
882
883 #ifdef PYTHON
884     JArray<jdouble>(PyObject *sequence) : java::lang::Object(env->get_vm_env()->NewDoubleArray(PySequence_Length(sequence))) {
885         length = env->getArrayLength((jarray) this$);
886         arrayElements elts = elements();
887         jdouble *buf = (jdouble *) elts;
888
889         for (int i = 0; i < length; i++) {
890             PyObject *obj = PySequence_GetItem(sequence, i);
891
892             if (!obj)
893                 break;
894
895             if (PyFloat_Check(obj))
896             {
897                 buf[i] = (jdouble) PyFloat_AS_DOUBLE(obj);
898                 Py_DECREF(obj);
899             }
900             else
901             {
902                 PyErr_SetObject(PyExc_TypeError, obj);
903                 Py_DECREF(obj);
904                 break;
905             }
906         }
907     }
908
909     PyObject *toSequence()
910     {
911         return toSequence(0, length);
912     }
913
914     PyObject *toSequence(int lo, int hi)
915     {
916         if (this$ == NULL)
917             Py_RETURN_NONE;
918
919         if (lo < 0) lo = length + lo;
920         if (lo < 0) lo = 0;
921         else if (lo > length) lo = length;
922         if (hi < 0) hi = length + hi;
923         if (hi < 0) hi = 0;
924         else if (hi > length) hi = length;
925         if (lo > hi) lo = hi;
926
927         PyObject *list = PyList_New(hi - lo);
928         arrayElements elts = elements();
929         jdouble *buf = (jdouble *) elts;
930
931         for (int i = lo; i < hi; i++)
932             PyList_SET_ITEM(list, i - lo, PyFloat_FromDouble((double) buf[i]));
933
934         return list;
935     }
936
937     PyObject *get(int n)
938     {
939         if (this$ != NULL)
940         {
941             if (n < 0)
942                 n = length + n;
943
944             if (n >= 0 && n < length)
945                 return PyFloat_FromDouble((double) (*this)[n]);
946         }
947
948         PyErr_SetString(PyExc_IndexError, "index out of range");
949         return NULL;
950     }
951
952     int set(int n, PyObject *obj)
953     {
954         if (this$ != NULL)
955         {
956             if (n < 0)
957                 n = length + n;
958
959             if (n >= 0 && n < length)
960             {
961                 if (!PyFloat_Check(obj))
962                 {
963                     PyErr_SetObject(PyExc_TypeError, obj);
964                     return -1;
965                 }
966
967                 elements()[n] = (jdouble) PyFloat_AS_DOUBLE(obj);
968                 return 0;
969             }
970         }
971
972         PyErr_SetString(PyExc_IndexError, "index out of range");
973         return -1;
974     }
975
976     PyObject *wrap() const;
977 #endif
978
979     jdouble operator[](int n) {
980         JNIEnv *vm_env = env->get_vm_env();
981         jboolean isCopy = 0;
982         jdouble *elts = (jdouble *)
983             vm_env->GetPrimitiveArrayCritical((jarray) this$, &isCopy);
984         jdouble value = elts[n];
985
986         vm_env->ReleasePrimitiveArrayCritical((jarray) this$, elts, 0);
987
988         return value;
989     }
990 };
991
992 template<> class JArray<jfloat> : public java::lang::Object {
993   public:
994     int length;
995
996     class arrayElements {
997     private:
998         jboolean isCopy;
999         jfloatArray array;
1000         jfloat *elts;
1001     public:
1002         arrayElements(jfloatArray array) {
1003             this->array = array;
1004             elts = env->get_vm_env()->GetFloatArrayElements(array, &isCopy);
1005         }
1006         virtual ~arrayElements() {
1007             env->get_vm_env()->ReleaseFloatArrayElements(array, elts, 0);
1008         }
1009         operator jfloat *() {
1010             return elts;
1011         }
1012     };
1013
1014     arrayElements elements() {
1015         return arrayElements((jfloatArray) this$);
1016     }
1017
1018     JArray<jfloat>(jobject obj) : java::lang::Object(obj) {
1019         length = this$ ? env->getArrayLength((jarray) this$) : 0;
1020     }
1021
1022     JArray<jfloat>(const JArray& obj) : java::lang::Object(obj) {
1023         length = obj.length;
1024     }
1025
1026     JArray<jfloat>(int n) : java::lang::Object(env->get_vm_env()->NewFloatArray(n)) {
1027         length = env->getArrayLength((jarray) this$);
1028     }
1029
1030 #ifdef PYTHON
1031     JArray<jfloat>(PyObject *sequence) : java::lang::Object(env->get_vm_env()->NewFloatArray(PySequence_Length(sequence))) {
1032         length = env->getArrayLength((jarray) this$);
1033         arrayElements elts = elements();
1034         jfloat *buf = (jfloat *) elts;
1035
1036         for (int i = 0; i < length; i++) {
1037             PyObject *obj = PySequence_GetItem(sequence, i);
1038
1039             if (!obj)
1040                 break;
1041
1042             if (PyFloat_Check(obj))
1043             {
1044                 buf[i] = (jfloat) PyFloat_AS_DOUBLE(obj);
1045                 Py_DECREF(obj);
1046             }
1047             else
1048             {
1049                 PyErr_SetObject(PyExc_TypeError, obj);
1050                 Py_DECREF(obj);
1051                 break;
1052             }
1053         }
1054     }
1055
1056     PyObject *toSequence()
1057     {
1058         return toSequence(0, length);
1059     }
1060
1061     PyObject *toSequence(int lo, int hi)
1062     {
1063         if (this$ == NULL)
1064             Py_RETURN_NONE;
1065
1066         if (lo < 0) lo = length + lo;
1067         if (lo < 0) lo = 0;
1068         else if (lo > length) lo = length;
1069         if (hi < 0) hi = length + hi;
1070         if (hi < 0) hi = 0;
1071         else if (hi > length) hi = length;
1072         if (lo > hi) lo = hi;
1073
1074         PyObject *list = PyList_New(hi - lo);
1075         arrayElements elts = elements();
1076         jfloat *buf = (jfloat *) elts;
1077
1078         for (int i = lo; i < hi; i++)
1079             PyList_SET_ITEM(list, i - lo, PyFloat_FromDouble((double) buf[i]));
1080
1081         return list;
1082     }
1083
1084     PyObject *get(int n)
1085     {
1086         if (this$ != NULL)
1087         {
1088             if (n < 0)
1089                 n = length + n;
1090
1091             if (n >= 0 && n < length)
1092                 return PyFloat_FromDouble((double) (*this)[n]);
1093         }
1094
1095         PyErr_SetString(PyExc_IndexError, "index out of range");
1096         return NULL;
1097     }
1098
1099     int set(int n, PyObject *obj)
1100     {
1101         if (this$ != NULL)
1102         {
1103             if (n < 0)
1104                 n = length + n;
1105
1106             if (n >= 0 && n < length)
1107             {
1108                 if (!PyFloat_Check(obj))
1109                 {
1110                     PyErr_SetObject(PyExc_TypeError, obj);
1111                     return -1;
1112                 }
1113
1114                 elements()[n] = (jfloat) PyFloat_AS_DOUBLE(obj);
1115                 return 0;
1116             }
1117         }
1118
1119         PyErr_SetString(PyExc_IndexError, "index out of range");
1120         return -1;
1121     }
1122
1123     PyObject *wrap() const;
1124 #endif
1125
1126     jfloat operator[](int n) {
1127         JNIEnv *vm_env = env->get_vm_env();
1128         jboolean isCopy = 0;
1129         jfloat *elts = (jfloat *)
1130             vm_env->GetPrimitiveArrayCritical((jarray) this$, &isCopy);
1131         jfloat value = elts[n];
1132
1133         vm_env->ReleasePrimitiveArrayCritical((jarray) this$, elts, 0);
1134
1135         return value;
1136     }
1137 };
1138
1139 template<> class JArray<jint> : public java::lang::Object {
1140   public:
1141     int length;
1142
1143     class arrayElements {
1144     private:
1145         jboolean isCopy;
1146         jintArray array;
1147         jint *elts;
1148     public:
1149         arrayElements(jintArray array) {
1150             this->array = array;
1151             elts = env->get_vm_env()->GetIntArrayElements(array, &isCopy);
1152         }
1153         virtual ~arrayElements() {
1154             env->get_vm_env()->ReleaseIntArrayElements(array, elts, 0);
1155         }
1156         operator jint *() {
1157             return elts;
1158         }
1159     };
1160
1161     arrayElements elements() {
1162         return arrayElements((jintArray) this$);
1163     }
1164
1165     JArray<jint>(jobject obj) : java::lang::Object(obj) {
1166         length = this$ ? env->getArrayLength((jarray) this$) : 0;
1167     }
1168
1169     JArray<jint>(const JArray& obj) : java::lang::Object(obj) {
1170         length = obj.length;
1171     }
1172
1173     JArray<jint>(int n) : java::lang::Object(env->get_vm_env()->NewIntArray(n)) {
1174         length = env->getArrayLength((jarray) this$);
1175     }
1176
1177 #ifdef PYTHON
1178     JArray<jint>(PyObject *sequence) : java::lang::Object(env->get_vm_env()->NewIntArray(PySequence_Length(sequence))) {
1179         length = env->getArrayLength((jarray) this$);
1180         arrayElements elts = elements();
1181         jint *buf = (jint *) elts;
1182
1183         for (int i = 0; i < length; i++) {
1184             PyObject *obj = PySequence_GetItem(sequence, i);
1185
1186             if (!obj)
1187                 break;
1188
1189             if (PyInt_Check(obj))
1190             {
1191                 buf[i] = (jint) PyInt_AS_LONG(obj);
1192                 Py_DECREF(obj);
1193             }
1194             else
1195             {
1196                 PyErr_SetObject(PyExc_TypeError, obj);
1197                 Py_DECREF(obj);
1198                 break;
1199             }
1200         }
1201     }
1202
1203     PyObject *toSequence()
1204     {
1205         return toSequence(0, length);
1206     }
1207
1208     PyObject *toSequence(int lo, int hi)
1209     {
1210         if (this$ == NULL)
1211             Py_RETURN_NONE;
1212
1213         if (lo < 0) lo = length + lo;
1214         if (lo < 0) lo = 0;
1215         else if (lo > length) lo = length;
1216         if (hi < 0) hi = length + hi;
1217         if (hi < 0) hi = 0;
1218         else if (hi > length) hi = length;
1219         if (lo > hi) lo = hi;
1220
1221         PyObject *list = PyList_New(hi - lo);
1222         arrayElements elts = elements();
1223         jint *buf = (jint *) elts;
1224
1225         for (int i = lo; i < hi; i++)
1226             PyList_SET_ITEM(list, i - lo, PyInt_FromLong(buf[i]));
1227
1228         return list;
1229     }
1230
1231     PyObject *get(int n)
1232     {
1233         if (this$ != NULL)
1234         {
1235             if (n < 0)
1236                 n = length + n;
1237
1238             if (n >= 0 && n < length)
1239                 return PyInt_FromLong((*this)[n]);
1240         }
1241
1242         PyErr_SetString(PyExc_IndexError, "index out of range");
1243         return NULL;
1244     }
1245
1246     int set(int n, PyObject *obj)
1247     {
1248         if (this$ != NULL)
1249         {
1250             if (n < 0)
1251                 n = length + n;
1252
1253             if (n >= 0 && n < length)
1254             {
1255                 if (!PyInt_Check(obj))
1256                 {
1257                     PyErr_SetObject(PyExc_TypeError, obj);
1258                     return -1;
1259                 }
1260
1261                 elements()[n] = (jint) PyInt_AS_LONG(obj);
1262                 return 0;
1263             }
1264         }
1265
1266         PyErr_SetString(PyExc_IndexError, "index out of range");
1267         return -1;
1268     }
1269
1270     PyObject *wrap() const;
1271 #endif
1272
1273     jint operator[](int n) {
1274         JNIEnv *vm_env = env->get_vm_env();
1275         jboolean isCopy = 0;
1276         jint *elts = (jint *)
1277             vm_env->GetPrimitiveArrayCritical((jarray) this$, &isCopy);
1278         jint value = elts[n];
1279
1280         vm_env->ReleasePrimitiveArrayCritical((jarray) this$, elts, 0);
1281
1282         return value;
1283     }
1284 };
1285
1286 template<> class JArray<jlong> : public java::lang::Object {
1287   public:
1288     int length;
1289
1290     class arrayElements {
1291     private:
1292         jboolean isCopy;
1293         jlongArray array;
1294         jlong *elts;
1295     public:
1296         arrayElements(jlongArray array) {
1297             this->array = array;
1298             elts = env->get_vm_env()->GetLongArrayElements(array, &isCopy);
1299         }
1300         virtual ~arrayElements() {
1301             env->get_vm_env()->ReleaseLongArrayElements(array, elts, 0);
1302         }
1303         operator jlong *() {
1304             return elts;
1305         }
1306     };
1307
1308     arrayElements elements() {
1309         return arrayElements((jlongArray) this$);
1310     }
1311
1312     JArray<jlong>(jobject obj) : java::lang::Object(obj) {
1313         length = this$ ? env->getArrayLength((jarray) this$) : 0;
1314     }
1315
1316     JArray<jlong>(const JArray& obj) : java::lang::Object(obj) {
1317         length = obj.length;
1318     }
1319
1320     JArray<jlong>(int n) : java::lang::Object(env->get_vm_env()->NewLongArray(n)) {
1321         length = env->getArrayLength((jarray) this$);
1322     }
1323
1324 #ifdef PYTHON
1325     JArray<jlong>(PyObject *sequence) : java::lang::Object(env->get_vm_env()->NewLongArray(PySequence_Length(sequence))) {
1326         length = env->getArrayLength((jarray) this$);
1327         arrayElements elts = elements();
1328         jlong *buf = (jlong *) elts;
1329
1330         for (int i = 0; i < length; i++) {
1331             PyObject *obj = PySequence_GetItem(sequence, i);
1332
1333             if (!obj)
1334                 break;
1335
1336             if (PyLong_Check(obj))
1337             {
1338                 buf[i] = (jlong) PyLong_AsLongLong(obj);
1339                 Py_DECREF(obj);
1340             }
1341             else
1342             {
1343                 PyErr_SetObject(PyExc_TypeError, obj);
1344                 Py_DECREF(obj);
1345                 break;
1346             }
1347         }
1348     }
1349
1350     PyObject *toSequence()
1351     {
1352         return toSequence(0, length);
1353     }
1354
1355     PyObject *toSequence(int lo, int hi)
1356     {
1357         if (this$ == NULL)
1358             Py_RETURN_NONE;
1359
1360         if (lo < 0) lo = length + lo;
1361         if (lo < 0) lo = 0;
1362         else if (lo > length) lo = length;
1363         if (hi < 0) hi = length + hi;
1364         if (hi < 0) hi = 0;
1365         else if (hi > length) hi = length;
1366         if (lo > hi) lo = hi;
1367
1368         PyObject *list = PyList_New(hi - lo);
1369         arrayElements elts = elements();
1370         jlong *buf = (jlong *) elts;
1371
1372         for (int i = lo; i < hi; i++)
1373             PyList_SET_ITEM(list, i - lo, PyLong_FromLongLong((long long) buf[i]));
1374
1375         return list;
1376     }
1377
1378     PyObject *get(int n)
1379     {
1380         if (this$ != NULL)
1381         {
1382             if (n < 0)
1383                 n = length + n;
1384
1385             if (n >= 0 && n < length)
1386                 return PyLong_FromLongLong((long long) (*this)[n]);
1387         }
1388
1389         PyErr_SetString(PyExc_IndexError, "index out of range");
1390         return NULL;
1391     }
1392
1393     int set(int n, PyObject *obj)
1394     {
1395         if (this$ != NULL)
1396         {
1397             if (n < 0)
1398                 n = length + n;
1399
1400             if (n >= 0 && n < length)
1401             {
1402                 if (!PyLong_Check(obj))
1403                 {
1404                     PyErr_SetObject(PyExc_TypeError, obj);
1405                     return -1;
1406                 }
1407
1408                 elements()[n] = (jlong) PyLong_AsLongLong(obj);
1409                 return 0;
1410             }
1411         }
1412
1413         PyErr_SetString(PyExc_IndexError, "index out of range");
1414         return -1;
1415     }
1416
1417     PyObject *wrap() const;
1418 #endif
1419
1420     jlong operator[](long n) {
1421         JNIEnv *vm_env = env->get_vm_env();
1422         jboolean isCopy = 0;
1423         jlong *elts = (jlong *)
1424             vm_env->GetPrimitiveArrayCritical((jarray) this$, &isCopy);
1425         jlong value = elts[n];
1426
1427         vm_env->ReleasePrimitiveArrayCritical((jarray) this$, elts, 0);
1428
1429         return value;
1430     }
1431 };
1432
1433 template<> class JArray<jshort> : public java::lang::Object {
1434   public:
1435     int length;
1436
1437     class arrayElements {
1438     private:
1439         jboolean isCopy;
1440         jshortArray array;
1441         jshort *elts;
1442     public:
1443         arrayElements(jshortArray array) {
1444             this->array = array;
1445             elts = env->get_vm_env()->GetShortArrayElements(array, &isCopy);
1446         }
1447         virtual ~arrayElements() {
1448             env->get_vm_env()->ReleaseShortArrayElements(array, elts, 0);
1449         }
1450         operator jshort *() {
1451             return elts;
1452         }
1453     };
1454
1455     arrayElements elements() {
1456         return arrayElements((jshortArray) this$);
1457     }
1458
1459     JArray<jshort>(jobject obj) : java::lang::Object(obj) {
1460         length = this$ ? env->getArrayLength((jarray) this$) : 0;
1461     }
1462
1463     JArray<jshort>(const JArray& obj) : java::lang::Object(obj) {
1464         length = obj.length;
1465     }
1466
1467     JArray<jshort>(int n) : java::lang::Object(env->get_vm_env()->NewShortArray(n)) {
1468         length = env->getArrayLength((jarray) this$);
1469     }
1470
1471 #ifdef PYTHON
1472     JArray<jshort>(PyObject *sequence) : java::lang::Object(env->get_vm_env()->NewShortArray(PySequence_Length(sequence))) {
1473         length = env->getArrayLength((jarray) this$);
1474         arrayElements elts = elements();
1475         jshort *buf = (jshort *) elts;
1476
1477         for (int i = 0; i < length; i++) {
1478             PyObject *obj = PySequence_GetItem(sequence, i);
1479
1480             if (!obj)
1481                 break;
1482
1483             if (PyInt_Check(obj))
1484             {
1485                 buf[i] = (jshort) PyInt_AS_LONG(obj);
1486                 Py_DECREF(obj);
1487             }
1488             else
1489             {
1490                 PyErr_SetObject(PyExc_TypeError, obj);
1491                 Py_DECREF(obj);
1492                 break;
1493             }
1494         }
1495     }
1496
1497     PyObject *toSequence()
1498     {
1499         return toSequence(0, length);
1500     }
1501
1502     PyObject *toSequence(int lo, int hi)
1503     {
1504         if (this$ == NULL)
1505             Py_RETURN_NONE;
1506
1507         if (lo < 0) lo = length + lo;
1508         if (lo < 0) lo = 0;
1509         else if (lo > length) lo = length;
1510         if (hi < 0) hi = length + hi;
1511         if (hi < 0) hi = 0;
1512         else if (hi > length) hi = length;
1513         if (lo > hi) lo = hi;
1514
1515         PyObject *list = PyList_New(hi - lo);
1516         arrayElements elts = elements();
1517         jshort *buf = (jshort *) elts;
1518
1519         for (int i = lo; i < hi; i++)
1520             PyList_SET_ITEM(list, i - lo, PyInt_FromLong(buf[i]));
1521
1522         return list;
1523     }
1524
1525     PyObject *get(int n)
1526     {
1527         if (this$ != NULL)
1528         {
1529             if (n < 0)
1530                 n = length + n;
1531
1532             if (n >= 0 && n < length)
1533                 return PyInt_FromLong((long) (*this)[n]);
1534         }
1535
1536         PyErr_SetString(PyExc_IndexError, "index out of range");
1537         return NULL;
1538     }
1539
1540     int set(int n, PyObject *obj)
1541     {
1542         if (this$ != NULL)
1543         {
1544             if (n < 0)
1545                 n = length + n;
1546
1547             if (n >= 0 && n < length)
1548             {
1549                 if (!PyInt_Check(obj))
1550                 {
1551                     PyErr_SetObject(PyExc_TypeError, obj);
1552                     return -1;
1553                 }
1554
1555                 elements()[n] = (jshort) PyInt_AS_LONG(obj);
1556                 return 0;
1557             }
1558         }
1559
1560         PyErr_SetString(PyExc_IndexError, "index out of range");
1561         return -1;
1562     }
1563
1564     PyObject *wrap() const;
1565 #endif
1566
1567     jshort operator[](int n) {
1568         JNIEnv *vm_env = env->get_vm_env();
1569         jboolean isCopy = 0;
1570         jshort *elts = (jshort *)
1571             vm_env->GetPrimitiveArrayCritical((jarray) this$, &isCopy);
1572         jshort value = elts[n];
1573
1574         vm_env->ReleasePrimitiveArrayCritical((jarray) this$, elts, 0);
1575
1576         return value;
1577     }
1578 };
1579
1580 #ifdef PYTHON
1581
1582 template<typename T> class t_JArray {
1583 public:
1584     PyObject_HEAD
1585     JArray<T> array;
1586
1587     static PyObject *wrap_Object(const JArray<T>& array)
1588     {
1589         if (!!array)
1590             return array.wrap();
1591
1592         Py_RETURN_NONE;
1593     }
1594 };
1595
1596 #endif
1597
1598 #endif /* _JArray_H */