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 static void createRawData (JNIEnv * env, jobject obj, void *ptr);
52 static void *getData (JNIEnv * env, jobject obj);
53
54 static jfieldID infid = NULL;
55 static jfieldID outfid = NULL;
56
57 /* Union used for type punning. */
58 union char_union
59 {
60 jbyte **jb;
61 jchar **jc;
62 char **c;
63 };
64
65 JNIEXPORT void JNICALL
Java_gnu_java_nio_charset_iconv_IconvDecoder_openIconv(JNIEnv * env,jobject obj,jstring jname)66 Java_gnu_java_nio_charset_iconv_IconvDecoder_openIconv (JNIEnv * env,
67 jobject obj,
68 jstring jname)
69 {
70 #if defined(HAVE_ICONV)
71 iconv_t iconv_object;
72 jclass cls;
73
74 const char *name = JCL_jstring_to_cstring (env, jname);
75 if (name == NULL)
76 return;
77
78 /* Cache fieldIDs for use in decode function. */
79 if (infid == NULL || outfid == NULL)
80 {
81 cls = (*env)->GetObjectClass (env, obj);
82 infid = (*env)->GetFieldID (env, cls, "inremaining", "I");
83 assert (infid != 0);
84 outfid = (*env)->GetFieldID (env, cls, "outremaining", "I");
85 assert (outfid != 0);
86 }
87
88 /* to java from "name", native java format depends on endianness */
89 #ifdef WORDS_BIGENDIAN
90 iconv_object = iconv_open ("UTF-16BE", name);
91 #else
92 iconv_object = iconv_open ("UTF-16LE", name);
93 #endif
94
95 JCL_free_cstring (env, jname, name);
96 if ((long) iconv_object == -1L)
97 {
98 JCL_ThrowException (env, "java/lang/IllegalArgumentException",
99 "Charset not available");
100 return;
101 }
102 createRawData (env, obj, (void *) iconv_object);
103 #else
104 JCL_ThrowException (env, "java/lang/IllegalArgumentException",
105 "iconv not available");
106 #endif
107 }
108
109 JNIEXPORT jint JNICALL
Java_gnu_java_nio_charset_iconv_IconvDecoder_decode(JNIEnv * env,jobject obj,jbyteArray inArr,jcharArray outArr,jint posIn,jint remIn,jint posOut,jint remOut)110 Java_gnu_java_nio_charset_iconv_IconvDecoder_decode (JNIEnv * env,
111 jobject obj,
112 jbyteArray inArr,
113 jcharArray outArr,
114 jint posIn, jint remIn,
115 jint posOut, jint remOut)
116 {
117 #if defined(HAVE_ICONV)
118 iconv_t iconv_object = getData (env, obj);
119 size_t retval;
120 union char_union in, out;
121 jbyte *input, *inputcopy;
122 jchar *output, *outputcopy;
123 size_t lenIn = (size_t) remIn;
124 size_t lenOut = (size_t) remOut * 2;
125
126 inputcopy = input = (*env)->GetByteArrayElements (env, inArr, 0);
127 outputcopy = output = (*env)->GetCharArrayElements (env, outArr, 0);
128
129 input += posIn;
130 output += posOut;
131
132 in.jb = &input;
133 out.jc = &output;
134 retval = iconv (iconv_object, (ICONV_CONST char **) in.c, &lenIn,
135 out.c, &lenOut);
136
137 /* XXX: Do we need to relase the input array? It's not modified. */
138 (*env)->ReleaseByteArrayElements (env, inArr, inputcopy, 0);
139 (*env)->ReleaseCharArrayElements (env, outArr, outputcopy, 0);
140
141 if (retval == (size_t) (-1))
142 {
143 if (errno == EILSEQ || errno == EINVAL)
144 retval = 1;
145 else
146 retval = 0;
147 }
148 else
149 retval = 0;
150
151 (*env)->SetIntField (env, obj, infid, (jint) lenIn);
152 (*env)->SetIntField (env, obj, outfid, (jint) (lenOut >> 1));
153
154 return (jint) retval;
155 #else
156 return -1;
157 #endif
158 }
159
160 JNIEXPORT void JNICALL
Java_gnu_java_nio_charset_iconv_IconvDecoder_closeIconv(JNIEnv * env,jobject obj)161 Java_gnu_java_nio_charset_iconv_IconvDecoder_closeIconv (JNIEnv * env,
162 jobject obj)
163 {
164 #if defined(HAVE_ICONV)
165 iconv_t iconv_object;
166 iconv_object = getData (env, obj);
167 iconv_close (iconv_object);
168 #endif
169 }
170
171
172 static void
createRawData(JNIEnv * env,jobject obj,void * ptr)173 createRawData (JNIEnv * env, jobject obj, void *ptr)
174 {
175 jclass cls;
176 jobject data;
177 jfieldID data_fid;
178
179 cls = (*env)->GetObjectClass (env, obj);
180 data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/Pointer;");
181 assert (data_fid != 0);
182
183 data = JCL_NewRawDataObject(env, ptr);
184
185 (*env)->SetObjectField (env, obj, data_fid, data);
186 }
187
188 static void *
getData(JNIEnv * env,jobject obj)189 getData (JNIEnv * env, jobject obj)
190 {
191 jclass cls;
192 jfieldID data_fid;
193 jobject data;
194
195 cls = (*env)->GetObjectClass (env, obj);
196 data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/Pointer;");
197 assert (data_fid != 0);
198 data = (*env)->GetObjectField (env, obj, data_fid);
199
200 return JCL_GetRawData(env, data);
201 }
202