1 /* gnu_java_nio_charset_iconv_IconvDecoder.c --
2 Copyright (C) 2005 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 #include <config.h>
39 #include <jcl.h>
40
41 #include <stdio.h>
42 #include <assert.h>
43 #include <errno.h>
44
45 #if defined(HAVE_ICONV)
46 #include <iconv.h>
47 #endif
48
49 #include "gnu_java_nio_charset_iconv_IconvDecoder.h"
50
51 #if defined(HAVE_ICONV)
52 static void createRawData (JNIEnv * env, jobject obj, void *ptr);
53 static void *getData (JNIEnv * env, jobject obj);
54
55 static jfieldID infid = NULL;
56 static jfieldID outfid = NULL;
57 #endif
58
59 /* Union used for type punning. */
60 union char_union
61 {
62 jbyte **jb;
63 jchar **jc;
64 char **c;
65 };
66
67 JNIEXPORT void JNICALL
Java_gnu_java_nio_charset_iconv_IconvDecoder_openIconv(JNIEnv * env UNUSED,jobject obj UNUSED,jstring jname UNUSED)68 Java_gnu_java_nio_charset_iconv_IconvDecoder_openIconv (JNIEnv * env UNUSED,
69 jobject obj UNUSED,
70 jstring jname UNUSED)
71 {
72 #if defined(HAVE_ICONV)
73 iconv_t iconv_object;
74 jclass cls;
75
76 const char *name = JCL_jstring_to_cstring (env, jname);
77 if (name == NULL)
78 return;
79
80 /* Cache fieldIDs for use in decode function. */
81 if (infid == NULL || outfid == NULL)
82 {
83 cls = (*env)->GetObjectClass (env, obj);
84 infid = (*env)->GetFieldID (env, cls, "inremaining", "I");
85 assert (infid != 0);
86 outfid = (*env)->GetFieldID (env, cls, "outremaining", "I");
87 assert (outfid != 0);
88 }
89
90 /* to java from "name", native java format depends on endianness */
91 #ifdef WORDS_BIGENDIAN
92 iconv_object = iconv_open ("UTF-16BE", name);
93 #else
94 iconv_object = iconv_open ("UTF-16LE", name);
95 #endif
96
97 JCL_free_cstring (env, jname, name);
98 if ((long) iconv_object == -1L)
99 {
100 JCL_ThrowException (env, "java/lang/IllegalArgumentException",
101 "Charset not available");
102 return;
103 }
104 createRawData (env, obj, (void *) iconv_object);
105 #else
106 JCL_ThrowException (env, "java/lang/IllegalArgumentException",
107 "iconv not available");
108 #endif
109 }
110
111 JNIEXPORT jint JNICALL
Java_gnu_java_nio_charset_iconv_IconvDecoder_decode(JNIEnv * env UNUSED,jobject obj UNUSED,jbyteArray inArr UNUSED,jcharArray outArr UNUSED,jint posIn UNUSED,jint remIn UNUSED,jint posOut UNUSED,jint remOut UNUSED)112 Java_gnu_java_nio_charset_iconv_IconvDecoder_decode (JNIEnv * env UNUSED,
113 jobject obj UNUSED,
114 jbyteArray inArr UNUSED,
115 jcharArray outArr UNUSED,
116 jint posIn UNUSED,
117 jint remIn UNUSED,
118 jint posOut UNUSED,
119 jint remOut UNUSED)
120 {
121 #if defined(HAVE_ICONV)
122 iconv_t iconv_object = getData (env, obj);
123 size_t retval;
124 union char_union in, out;
125 jbyte *input, *inputcopy;
126 jchar *output, *outputcopy;
127 size_t lenIn = (size_t) remIn;
128 size_t lenOut = (size_t) remOut * 2;
129
130 inputcopy = input = (*env)->GetByteArrayElements (env, inArr, 0);
131 outputcopy = output = (*env)->GetCharArrayElements (env, outArr, 0);
132
133 input += posIn;
134 output += posOut;
135
136 in.jb = &input;
137 out.jc = &output;
138 retval = iconv (iconv_object, (ICONV_CONST char **) in.c, &lenIn,
139 out.c, &lenOut);
140
141 /* XXX: Do we need to relase the input array? It's not modified. */
142 (*env)->ReleaseByteArrayElements (env, inArr, inputcopy, 0);
143 (*env)->ReleaseCharArrayElements (env, outArr, outputcopy, 0);
144
145 if (retval == (size_t) (-1))
146 {
147 if (errno == EILSEQ)
148 retval = 1;
149 else
150 retval = 0;
151 }
152 else
153 retval = 0;
154
155 (*env)->SetIntField (env, obj, infid, (jint) lenIn);
156 (*env)->SetIntField (env, obj, outfid, (jint) (lenOut >> 1));
157
158 return (jint) retval;
159 #else
160 return -1;
161 #endif
162 }
163
164 JNIEXPORT void JNICALL
Java_gnu_java_nio_charset_iconv_IconvDecoder_closeIconv(JNIEnv * env UNUSED,jobject obj UNUSED)165 Java_gnu_java_nio_charset_iconv_IconvDecoder_closeIconv (JNIEnv * env UNUSED,
166 jobject obj UNUSED)
167 {
168 #if defined(HAVE_ICONV)
169 iconv_t iconv_object;
170 iconv_object = getData (env, obj);
171 iconv_close (iconv_object);
172 #endif
173 }
174
175
176 #if defined(HAVE_ICONV)
177 static void
createRawData(JNIEnv * env,jobject obj,void * ptr)178 createRawData (JNIEnv * env, jobject obj, void *ptr)
179 {
180 jclass cls;
181 jobject data;
182 jfieldID data_fid;
183
184 cls = (*env)->GetObjectClass (env, obj);
185 data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/Pointer;");
186 assert (data_fid != 0);
187
188 data = JCL_NewRawDataObject(env, ptr);
189
190 (*env)->SetObjectField (env, obj, data_fid, data);
191 }
192
193 static void *
getData(JNIEnv * env,jobject obj)194 getData (JNIEnv * env, jobject obj)
195 {
196 jclass cls;
197 jfieldID data_fid;
198 jobject data;
199
200 cls = (*env)->GetObjectClass (env, obj);
201 data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/Pointer;");
202 assert (data_fid != 0);
203 data = (*env)->GetObjectField (env, obj, data_fid);
204
205 return JCL_GetRawData(env, data);
206 }
207 #endif
208
209