1 /*
2 * Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <locale.h>
30 #include <langinfo.h>
31 #include <iconv.h>
32
33 #include "utf.h"
34
35 /* Global variables */
36
37 /*
38 * Initialize all utf processing.
39 */
40 struct UtfInst *JNICALL
utfInitialize(char * options)41 utfInitialize(char *options)
42 {
43 struct UtfInst *ui;
44 char *codeset;
45
46 ui = (struct UtfInst*)calloc(sizeof(struct UtfInst), 1);
47 ui->iconvToPlatform = (void *)-1;
48 ui->iconvFromPlatform = (void *)-1;
49
50 /* Set the locale from the environment */
51 (void)setlocale(LC_ALL, "");
52
53 /* Get the codeset name */
54 codeset = (char*)nl_langinfo(CODESET);
55 if ( codeset == NULL || codeset[0] == 0 ) {
56 return ui;
57 }
58
59 /* If we don't need this, skip it */
60 if (strcmp(codeset, "UTF-8") == 0 || strcmp(codeset, "utf8") == 0 ) {
61 return ui;
62 }
63
64 /* Open conversion descriptors */
65 ui->iconvToPlatform = iconv_open(codeset, "UTF-8");
66 if ( ui->iconvToPlatform == (void *)-1 ) {
67 UTF_ERROR("Failed to complete iconv_open() setup");
68 }
69 ui->iconvFromPlatform = iconv_open("UTF-8", codeset);
70 if ( ui->iconvFromPlatform == (void *)-1 ) {
71 UTF_ERROR("Failed to complete iconv_open() setup");
72 }
73 return ui;
74 }
75
76 /*
77 * Terminate all utf processing
78 */
79 void JNICALL
utfTerminate(struct UtfInst * ui,char * options)80 utfTerminate(struct UtfInst *ui, char *options)
81 {
82 if ( ui->iconvFromPlatform != (void *)-1 ) {
83 (void)iconv_close(ui->iconvFromPlatform);
84 }
85 if ( ui->iconvToPlatform != (void *)-1 ) {
86 (void)iconv_close(ui->iconvToPlatform);
87 }
88 ui->iconvToPlatform = (void *)-1;
89 ui->iconvFromPlatform = (void *)-1;
90 (void)free(ui);
91 }
92
93 /*
94 * Do iconv() conversion.
95 * Returns length or -1 if output overflows.
96 */
97 static int
iconvConvert(iconv_t ic,char * bytes,int len,char * output,int outputMaxLen)98 iconvConvert(iconv_t ic, char *bytes, int len, char *output, int outputMaxLen)
99 {
100 int outputLen = 0;
101
102 UTF_ASSERT(bytes);
103 UTF_ASSERT(len>=0);
104 UTF_ASSERT(output);
105 UTF_ASSERT(outputMaxLen>len);
106
107 output[0] = 0;
108 outputLen = 0;
109
110 if ( ic != (iconv_t)(void *)-1 ) {
111 int returnValue;
112 size_t inLeft;
113 size_t outLeft;
114 char *inbuf;
115 char *outbuf;
116
117 inbuf = bytes;
118 outbuf = output;
119 inLeft = len;
120 outLeft = outputMaxLen;
121 returnValue = iconv(ic, (void*)&inbuf, &inLeft, &outbuf, &outLeft);
122 if ( returnValue >= 0 && inLeft==0 ) {
123 outputLen = outputMaxLen-outLeft;
124 output[outputLen] = 0;
125 return outputLen;
126 }
127
128 /* Failed to do the conversion */
129 return -1;
130 }
131
132 /* Just copy bytes */
133 outputLen = len;
134 (void)memcpy(output, bytes, len);
135 output[len] = 0;
136 return outputLen;
137 }
138
139 /*
140 * Convert UTF-8 to Platform Encoding.
141 * Returns length or -1 if output overflows.
142 */
143 int JNICALL
utf8ToPlatform(struct UtfInst * ui,jbyte * utf8,int len,char * output,int outputMaxLen)144 utf8ToPlatform(struct UtfInst*ui, jbyte *utf8, int len, char *output, int outputMaxLen)
145 {
146 /* Negative length is an error */
147 if ( len < 0 ) {
148 return -1;
149 }
150
151 /* Zero length is ok, but we don't need to do much */
152 if ( len == 0 ) {
153 output[0] = 0;
154 return 0;
155 }
156
157 return iconvConvert(ui->iconvToPlatform, (char*)utf8, len, output, outputMaxLen);
158 }
159
160 /*
161 * Convert Platform Encoding to UTF-8.
162 * Returns length or -1 if output overflows.
163 */
164 int JNICALL
utf8FromPlatform(struct UtfInst * ui,char * str,int len,jbyte * output,int outputMaxLen)165 utf8FromPlatform(struct UtfInst*ui, char *str, int len, jbyte *output, int outputMaxLen)
166 {
167 /* Negative length is an error */
168 if ( len < 0 ) {
169 return -1;
170 }
171
172 /* Zero length is ok, but we don't need to do much */
173 if ( len == 0 ) {
174 output[0] = 0;
175 return 0;
176 }
177
178 return iconvConvert(ui->iconvFromPlatform, str, len, (char*)output, outputMaxLen);
179 }
180