2000-01-31 12:53:47 +08:00
|
|
|
// Input_iconv.java -- Java side of iconv() reader.
|
|
|
|
|
2000-03-08 03:55:28 +08:00
|
|
|
/* Copyright (C) 2000 Free Software Foundation
|
2000-01-31 12:53:47 +08:00
|
|
|
|
|
|
|
This file is part of libgcj.
|
|
|
|
|
|
|
|
This software is copyrighted work licensed under the terms of the
|
|
|
|
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
|
|
|
details. */
|
|
|
|
|
|
|
|
/* Author: Tom Tromey <tromey@redhat.com>. */
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <gcj/cni.h>
|
|
|
|
#include <jvm.h>
|
|
|
|
|
|
|
|
#include <gnu/gcj/convert/Input_iconv.h>
|
|
|
|
#include <gnu/gcj/convert/Output_iconv.h>
|
|
|
|
#include <java/io/UnsupportedEncodingException.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_ICONV
|
|
|
|
#include <iconv.h>
|
2000-06-16 09:11:12 +08:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static inline size_t
|
|
|
|
iconv_adapter (size_t (*iconv_f) (iconv_t, T, size_t *, char **, size_t *),
|
|
|
|
iconv_t handle, char **inbuf, size_t *inavail,
|
|
|
|
char **outbuf, size_t *outavail)
|
|
|
|
{
|
|
|
|
return (*iconv_f) (handle, (T) inbuf, inavail, outbuf, outavail);
|
|
|
|
}
|
|
|
|
|
2000-01-31 12:53:47 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
void
|
|
|
|
gnu::gcj::convert::Input_iconv::init (jstring encoding)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_ICONV
|
|
|
|
jsize len = _Jv_GetStringUTFLength (encoding);
|
|
|
|
char buffer[len];
|
|
|
|
_Jv_GetStringUTFRegion (encoding, 0, len, buffer);
|
|
|
|
|
|
|
|
iconv_t h = iconv_open ("UCS-2", buffer);
|
|
|
|
if (h == (iconv_t) -1)
|
|
|
|
JvThrow (new java::io::UnsupportedEncodingException);
|
|
|
|
|
|
|
|
JvAssert (h != NULL);
|
|
|
|
handle = reinterpret_cast<gnu::gcj::RawData *> (h);
|
|
|
|
#else /* HAVE_ICONV */
|
|
|
|
// If no iconv, just throw an exception.
|
|
|
|
JvThrow (new java::io::UnsupportedEncodingException);
|
|
|
|
#endif /* HAVE_ICONV */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gnu::gcj::convert::Input_iconv::finalize (void)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_ICONV
|
2000-02-10 08:14:54 +08:00
|
|
|
if (handle != NULL)
|
2000-01-31 12:53:47 +08:00
|
|
|
{
|
|
|
|
iconv_close ((iconv_t) handle);
|
|
|
|
handle = NULL;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_ICONV */
|
|
|
|
}
|
|
|
|
|
|
|
|
jint
|
|
|
|
gnu::gcj::convert::Input_iconv::read (jcharArray outbuffer,
|
|
|
|
jint outpos, jint count)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_ICONV
|
|
|
|
jbyte *bytes = elements (inbuffer);
|
|
|
|
jchar *out = elements (outbuffer);
|
|
|
|
size_t inavail = inlength - inpos;
|
|
|
|
size_t old_in = inavail;
|
|
|
|
size_t outavail = count;
|
|
|
|
size_t old_out = outavail;
|
|
|
|
|
2000-06-16 09:11:12 +08:00
|
|
|
char *inbuf = (char *) &bytes[inpos];
|
2000-01-31 16:56:09 +08:00
|
|
|
char *outbuf = (char *) &out[outpos];
|
|
|
|
|
2000-06-16 09:11:12 +08:00
|
|
|
size_t r = iconv_adapter (iconv, (iconv_t) handle,
|
|
|
|
&inbuf, &inavail,
|
|
|
|
&outbuf, &outavail);
|
2000-01-31 12:53:47 +08:00
|
|
|
// FIXME: what if R==-1?
|
|
|
|
|
|
|
|
inpos += old_in - inavail;
|
|
|
|
return old_out - outavail;
|
|
|
|
#else /* HAVE_ICONV */
|
|
|
|
return -1;
|
|
|
|
#endif /* HAVE_ICONV */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gnu::gcj::convert::Output_iconv::init (jstring encoding)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_ICONV
|
|
|
|
jsize len = _Jv_GetStringUTFLength (encoding);
|
|
|
|
char buffer[len];
|
|
|
|
_Jv_GetStringUTFRegion (encoding, 0, len, buffer);
|
|
|
|
|
|
|
|
iconv_t h = iconv_open (buffer, "UCS-2");
|
|
|
|
if (h == (iconv_t) -1)
|
|
|
|
JvThrow (new java::io::UnsupportedEncodingException);
|
|
|
|
|
|
|
|
JvAssert (h != NULL);
|
|
|
|
handle = reinterpret_cast<gnu::gcj::RawData *> (h);
|
|
|
|
#else /* HAVE_ICONV */
|
|
|
|
// If no iconv, just throw an exception.
|
|
|
|
JvThrow (new java::io::UnsupportedEncodingException);
|
|
|
|
#endif /* HAVE_ICONV */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gnu::gcj::convert::Output_iconv::finalize (void)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_ICONV
|
2000-02-10 08:14:54 +08:00
|
|
|
if (handle != NULL)
|
2000-01-31 12:53:47 +08:00
|
|
|
{
|
|
|
|
iconv_close ((iconv_t) handle);
|
|
|
|
handle = NULL;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_ICONV */
|
|
|
|
}
|
|
|
|
|
|
|
|
jint
|
|
|
|
gnu::gcj::convert::Output_iconv::write (jcharArray inbuffer,
|
|
|
|
jint inpos, jint count)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_ICONV
|
|
|
|
jchar *chars = elements (inbuffer);
|
|
|
|
jbyte *out = elements (buf);
|
|
|
|
|
|
|
|
size_t inavail = count;
|
|
|
|
size_t old_in = count;
|
|
|
|
|
|
|
|
size_t outavail = buf->length - count;
|
|
|
|
size_t old_out = outavail;
|
|
|
|
|
2000-06-16 09:11:12 +08:00
|
|
|
char *inbuf = (char *) &chars[inpos];
|
2000-01-31 16:56:09 +08:00
|
|
|
char *outbuf = (char *) &out[count];
|
|
|
|
|
2000-06-16 09:11:12 +08:00
|
|
|
size_t r = iconv_adapter (iconv, (iconv_t) handle,
|
|
|
|
&inbuf, &inavail,
|
|
|
|
&outbuf, &outavail);
|
2000-01-31 12:53:47 +08:00
|
|
|
// FIXME: what if R==-1?
|
|
|
|
|
|
|
|
count += old_out - outavail;
|
|
|
|
return old_in - inavail;
|
|
|
|
#else /* HAVE_ICONV */
|
|
|
|
return -1;
|
|
|
|
#endif /* HAVE_ICONV */
|
|
|
|
}
|