summaryrefslogtreecommitdiffstats
path: root/icu/src/main
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2010-04-02 17:19:21 -0700
committerElliott Hughes <enh@google.com>2010-04-02 17:58:45 -0700
commitccb8b92211a3e87acaf6486c8d4423c2053b8b5e (patch)
tree5898c2d9793dcf05f83192c17183f09e13b8920a /icu/src/main
parent3604384c5f53c83383ce85f838901e46b0105e5e (diff)
downloadlibcore-ccb8b92211a3e87acaf6486c8d4423c2053b8b5e.zip
libcore-ccb8b92211a3e87acaf6486c8d4423c2053b8b5e.tar.gz
libcore-ccb8b92211a3e87acaf6486c8d4423c2053b8b5e.tar.bz2
More Charset/ICU cleanup.
I've been feeling guilty about leaving broken double-checked locking (missing the "volatile") in harmony's Charset code. A quick investigation showed that the method that it's intended to optimize is basically never called, and the RI's documentation explicitly says "don't call this; it's slow". So this patch fixes that. I've also improved our documentation. I've also deleted a bunch of dead code. I've also tidied up some dodgy native string handling. Change-Id: Iad69ebb3459d9cc4c4ff37b255d458b83fe40132
Diffstat (limited to 'icu/src/main')
-rw-r--r--icu/src/main/java/com/ibm/icu4jni/charset/CharsetICU.java38
-rw-r--r--icu/src/main/java/com/ibm/icu4jni/charset/CharsetProviderICU.java50
-rw-r--r--icu/src/main/java/com/ibm/icu4jni/charset/NativeConverter.java377
-rw-r--r--icu/src/main/native/NativeConverter.cpp373
4 files changed, 146 insertions, 692 deletions
diff --git a/icu/src/main/java/com/ibm/icu4jni/charset/CharsetICU.java b/icu/src/main/java/com/ibm/icu4jni/charset/CharsetICU.java
index 155f966..fe0f920 100644
--- a/icu/src/main/java/com/ibm/icu4jni/charset/CharsetICU.java
+++ b/icu/src/main/java/com/ibm/icu4jni/charset/CharsetICU.java
@@ -5,7 +5,7 @@
*******************************************************************************
*
*******************************************************************************
-*/
+*/
package com.ibm.icu4jni.charset;
@@ -36,52 +36,52 @@ public final class CharsetICU extends Charset {
long converterHandle = NativeConverter.openConverter(icuCanonicalName);
return new CharsetDecoderICU(this, converterHandle);
}
-
+
// hardCoded list of replacement bytes
- private static final Map subByteMap = new HashMap();
- static{
- subByteMap.put("UTF-32",new byte[]{0x00, 0x00, (byte)0xfe, (byte)0xff});
- subByteMap.put("ibm-16684_P110-2003",new byte[]{0x40, 0x40}); // make \u3000 the sub char
- subByteMap.put("ibm-971_P100-1995",new byte[]{(byte)0xa1, (byte)0xa1}); // make \u3000 the sub char
+ private static final Map<String, byte[]> subByteMap = new HashMap<String, byte[]>();
+ static {
+ subByteMap.put("UTF-32", new byte[]{0x00, 0x00, (byte)0xfe, (byte)0xff});
+ subByteMap.put("ibm-16684_P110-2003", new byte[]{0x40, 0x40}); // make \u3000 the sub char
+ subByteMap.put("ibm-971_P100-1995", new byte[]{(byte)0xa1, (byte)0xa1}); // make \u3000 the sub char
}
/**
* Returns a new encoder object of the charset
* @return a new encoder
* @stable ICU 2.4
*/
- public CharsetEncoder newEncoder(){
+ public CharsetEncoder newEncoder() {
// the arrays are locals and not
// instance variables since the
- // methods on this class need to
+ // methods on this class need to
// be thread safe
long converterHandle = NativeConverter.openConverter(icuCanonicalName);
-
+
//According to the contract all converters should have non-empty replacement
byte[] replacement = NativeConverter.getSubstitutionBytes(converterHandle);
- try{
+ try {
return new CharsetEncoderICU(this,converterHandle, replacement);
- }catch(IllegalArgumentException ex){
+ } catch (IllegalArgumentException ex) {
// work around for the non-sensical check in the nio API that
// a substitution character must be mappable while decoding!!
- replacement = (byte[])subByteMap.get(icuCanonicalName);
- if(replacement==null){
+ replacement = subByteMap.get(icuCanonicalName);
+ if (replacement == null) {
replacement = new byte[NativeConverter.getMinBytesPerChar(converterHandle)];
- for(int i=0; i<replacement.length; i++){
+ for(int i = 0; i < replacement.length; ++i) {
replacement[i]= 0x3f;
}
}
NativeConverter.setSubstitutionBytes(converterHandle, replacement, replacement.length);
return new CharsetEncoderICU(this,converterHandle, replacement);
}
- }
-
+ }
+
/**
* Ascertains if a charset is a sub set of this charset
* @param cs charset to test
* @return true if the given charset is a subset of this charset
* @stable ICU 2.4
- *
+ *
* //CSDL: major changes by Jack
*/
public boolean contains(Charset cs){
@@ -90,7 +90,7 @@ public final class CharsetICU extends Charset {
} else if (this.equals(cs)) {
return true;
}
-
+
long converterHandle1 = 0;
long converterHandle2 = 0;
diff --git a/icu/src/main/java/com/ibm/icu4jni/charset/CharsetProviderICU.java b/icu/src/main/java/com/ibm/icu4jni/charset/CharsetProviderICU.java
deleted file mode 100644
index 0479223..0000000
--- a/icu/src/main/java/com/ibm/icu4jni/charset/CharsetProviderICU.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
-*******************************************************************************
-* Copyright (C) 1996-2005, International Business Machines Corporation and *
-* others. All Rights Reserved. *
-*******************************************************************************
-*
-*******************************************************************************
-*/
-
-package com.ibm.icu4jni.charset;
-
-import java.nio.charset.Charset;
-import java.nio.charset.spi.CharsetProvider;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-public final class CharsetProviderICU extends CharsetProvider {
- public CharsetProviderICU() {
- }
-
- @Override
- public Charset charsetForName(String charsetName) {
- return NativeConverter.charsetForName(charsetName);
- }
-
- @Override
- public Iterator<Charset> charsets() {
- ArrayList<Charset> result = new ArrayList<Charset>();
- for (String charsetName : NativeConverter.getAvailable()) {
- result.add(charsetForName(charsetName));
- }
- return result.iterator();
- }
-
- /**
- * Implements Charset.availableCharsets.
- */
- public SortedMap<String, Charset> initAvailableCharsets() {
- SortedMap<String, Charset> result =
- new TreeMap<String, Charset>(String.CASE_INSENSITIVE_ORDER);
- for (String charset : NativeConverter.getAvailable()) {
- if (!result.containsKey(charset)) {
- result.put(charset, charsetForName(charset));
- }
- }
- return result;
- }
-}
diff --git a/icu/src/main/java/com/ibm/icu4jni/charset/NativeConverter.java b/icu/src/main/java/com/ibm/icu4jni/charset/NativeConverter.java
index eefe3d5..6a97c27 100644
--- a/icu/src/main/java/com/ibm/icu4jni/charset/NativeConverter.java
+++ b/icu/src/main/java/com/ibm/icu4jni/charset/NativeConverter.java
@@ -5,28 +5,21 @@
*******************************************************************************
*
*******************************************************************************
-*/
+*/
package com.ibm.icu4jni.charset;
import java.nio.charset.Charset;
-/**
- * Class for accessing the underlying JNI methods
- * @internal ICU 2.4
- */
-final class NativeConverter {
-
- //Native methods
-
+public final class NativeConverter {
/**
* Converts an array of bytes containing characters in an external
* encoding into an array of Unicode characters. This method allows
- * a buffer by buffer conversion of a data stream. The state of the
- * conversion is saved between calls to convert. Among other things,
+ * buffer-by-buffer conversion of a data stream. The state of the
+ * conversion is saved between calls. Among other things,
* this means multibyte input sequences can be split between calls.
- * If a call to convert results in an Error, the conversion may be
- * continued by calling convert again with suitably modified parameters.
+ * If a call to results in an error, the conversion may be
+ * continued by calling this method again with suitably modified parameters.
* All conversions should be finished with a call to the flush method.
*
* @param converterHandle Address of converter object created by C code
@@ -34,78 +27,22 @@ final class NativeConverter {
* @param inEnd stop conversion at this offset in input array (exclusive).
* @param output character array to receive conversion result.
* @param outEnd stop writing to output array at this offset (exclusive).
- * @param data integer array containing the following data
+ * @param data integer array containing the following data
* data[0] = inputOffset
* data[1] = outputOffset
* @return int error code returned by ICU
* @internal ICU 2.4
*/
-
- public static final native int convertByteToChar( long converterHandle,
- byte[] input, int inEnd,
- char[] output, int outEnd,
- int[] data,
- boolean flush);
- /**
- * Converts an array of bytes containing characters in an external
- * encoding into an array of Unicode characters. This method allows
- * a buffer by buffer conversion of a data stream. The state of the
- * conversion is saved between calls to convert. Among other things,
- * this means multibyte input sequences can be split between calls.
- * If a call to convert results in an Error, the conversion may be
- * continued by calling convert again with suitably modified parameters.
- * All conversions should be finished with a call to the flush method.
- *
- * @param converterHandle Address of converter object created by C code
- * @param input byte array containing text to be converted.
- * @param inEnd stop conversion at this offset in input array (exclusive).
- * @param output character array to receive conversion result.
- * @param outEnd stop writing to output array at this offset (exclusive).
- * @param data integer array containing the following data
- * data[0] = inputOffset
- * data[1] = outputOffset
- * @return int error code returned by ICU
- * @internal ICU 2.4
- */
- public static final native int decode( long converterHandle,
- byte[] input, int inEnd,
- char[] output, int outEnd,
- int[] data,
- boolean flush);
- /**
- * Converts an array of Unicode chars containing characters in an
- * external encoding into an array of bytes. This method allows
- * a buffer by buffer conversion of a data stream. The state of the
- * conversion is saved between calls to convert. Among other things,
- * this means multibyte input sequences can be split between calls.
- * If a call to convert results in an Error, the conversion may be
- * continued by calling convert again with suitably modified parameters.
- * All conversions should be finished with a call to the flush method.
- *
- * @param converterHandle Address of converter object created by C code
- * @param input char array containing text to be converted.
- * @param inEnd stop conversion at this offset in input array (exclusive).
- * @param output byte array to receive conversion result.
- * @param outEnd stop writing to output array at this offset (exclusive).
- * @param data integer array containing the following data
- * data[0] = inputOffset
- * data[1] = outputOffset
- * @return int error code returned by ICU
- * @internal ICU 2.4
- */
- public static final native int convertCharToByte(long converterHandle,
- char[] input, int inEnd,
- byte[] output, int outEnd,
- int[] data,
- boolean flush);
+ public static native int decode(long converterHandle, byte[] input, int inEnd,
+ char[] output, int outEnd, int[] data, boolean flush);
+
/**
- * Converts an array of Unicode chars containing characters in an
- * external encoding into an array of bytes. This method allows
- * a buffer by buffer conversion of a data stream. The state of the
+ * Converts an array of Unicode chars to an array of bytes in an external encoding.
+ * This method allows a buffer by buffer conversion of a data stream. The state of the
* conversion is saved between calls to convert. Among other things,
* this means multibyte input sequences can be split between calls.
- * If a call to convert results in an Error, the conversion may be
- * continued by calling convert again with suitably modified parameters.
+ * If a call results in an error, the conversion may be
+ * continued by calling this method again with suitably modified parameters.
* All conversions should be finished with a call to the flush method.
*
* @param converterHandle Address of converter object created by C code
@@ -113,283 +50,71 @@ final class NativeConverter {
* @param inEnd stop conversion at this offset in input array (exclusive).
* @param output byte array to receive conversion result.
* @param outEnd stop writing to output array at this offset (exclusive).
- * @param data integer array containing the following data
+ * @param data integer array containing the following data
* data[0] = inputOffset
* data[1] = outputOffset
* @return int error code returned by ICU
* @internal ICU 2.4
- */
- public static final native int encode(long converterHandle,
- char[] input, int inEnd,
- byte[] output, int outEnd,
- int[] data,
- boolean flush);
+ */
+ public static native int encode(long converterHandle, char[] input, int inEnd,
+ byte[] output, int outEnd, int[] data, boolean flush);
+
/**
* Writes any remaining output to the output buffer and resets the
- * converter to its initial state.
+ * converter to its initial state.
*
* @param converterHandle Address of converter object created by C code
* @param output byte array to receive flushed output.
* @param outEnd stop writing to output array at this offset (exclusive).
* @return int error code returned by ICU
- * @param data integer array containing the following data
+ * @param data integer array containing the following data
* data[0] = inputOffset
* data[1] = outputOffset
* @internal ICU 2.4
- */
- public static final native int flushCharToByte(long converterHandle,
- byte[] output,
- int outEnd,
- int[] data);
+ */
+ public static native int flushCharToByte(long converterHandle, byte[] output, int outEnd, int[] data);
+
/**
* Writes any remaining output to the output buffer and resets the
- * converter to its initial state.
+ * converter to its initial state.
*
* @param converterHandle Address of converter object created by the native code
* @param output char array to receive flushed output.
* @param outEnd stop writing to output array at this offset (exclusive).
* @return int error code returned by ICU
- * @param data integer array containing the following data
+ * @param data integer array containing the following data
* data[0] = inputOffset
* data[1] = outputOffset
* @internal ICU 2.4
- */
- public static final native int flushByteToChar(long converterHandle,
- char[] output,
- int outEnd,
- int[] data);
-
- /**
- * Open the converter with the specified encoding
- *
- * @param converterHandle long array for recieving the adress of converter object
- * created by the native code
- * @param encoding string representing encoding
- * @return int error code returned by ICU
- * @internal ICU 2.4
- */
- public static final native long openConverter(String encoding);
- /**
- * Resets the ByteToChar (toUnicode) state of specified converter
- *
- * @param converterHandle Address of converter object created by the native code
- * @internal ICU 2.4
- */
- public static final native void resetByteToChar(long converterHandle);
-
- /**
- * Resets the CharToByte (fromUnicode) state of specified converter
- *
- * @param converterHandle Address of converter object created by the native code
- * @internal ICU 2.4
- */
- public static final native void resetCharToByte(long converterHandle);
-
- /**
- * Closes the specified converter and releases the resources
- *
- * @param converterHandle Address of converter object created by the native code
- * @internal ICU 2.4
- */
- public static final native void closeConverter(long converterHandle);
-
- /**
- * Sets the substitution Unicode chars of the specified converter used
- * by encoder
- * @param converterHandle Address of converter object created by the native code
- * @param subChars array of chars to used for substitution
- * @param length length of the array
- * @return int error code returned by ICU
- * @internal ICU 2.4
- */
- public static final native int setSubstitutionChars( long converterHandle,
- char[] subChars,int length);
- /**
- * Sets the substitution bytes of the specified converter used by decoder
- *
- * @param converterHandle Address of converter object created by the native code
- * @param subChars array of bytes to used for substitution
- * @param length length of the array
- * @return int error code returned by ICU
- * @internal ICU 2.4
- */
- public static final native int setSubstitutionBytes( long converterHandle,
- byte[] subChars,int length);
- /**
- * Sets the substitution mode of CharToByte(fromUnicode) for the specified converter
- *
- * @param converterHandle Address of converter object created by the native code
- * @param mode to set the true/false
- * @return int error code returned by ICU
- * @internal ICU 2.4
- */
- public static final native int setSubstitutionModeCharToByte(long converterHandle,
- boolean mode);
- /**
- * Sets the substitution mode of CharToByte(fromUnicode) for the specified converter
- *
- * @param converterHandle Address of converter object created by the native code
- * @param mode to set the true/false
- * @return int error code returned by ICU
- * @internal ICU 3.6
- */
- public static final native int setSubstitutionModeByteToChar(long converterHandle,
- boolean mode);
- /**
- * Gets the numnber of invalid bytes in the specified converter object
- * for the last error that has occured
- *
- * @param converterHandle Address of converter object created by the native code
- * @param length array of int to recieve length of the array
- * @return int error code returned by ICU
- * @internal ICU 2.4
- */
- public static final native int countInvalidBytes(long converterHandle, int[] length);
-
- /**
- * Gets the numnber of invalid chars in the specified converter object
- * for the last error that has occured
- *
- * @param converterHandle Address of converter object created by the native code
- * @param length array of int to recieve length of the array
- * @return int error code returned by ICU
- * @internal ICU 2.4
- */
- public static final native int countInvalidChars(long converterHandle, int[] length);
-
- /**
- * Gets the number of bytes needed for converting a char
- *
- * @param converterHandle Address of converter object created by the native code
- * @return number of bytes needed
- * @internal ICU 2.4
- */
- public static final native int getMaxBytesPerChar(long converterHandle);
-
- /**
- * Gets the number of bytes needed for converting a char
- *
- * @param converterHandle Address of converter object created by the native code
- * @return number of bytes needed
- * @internal ICU 3.2
- */
- public static final native int getMinBytesPerChar(long converterHandle);
-
- /**
- * Gets the average numnber of bytes needed for converting a char
- *
- * @param converterHandle Address of converter object created by the native code
- * @return number of bytes needed
- * @internal ICU 2.4
- */
- public static final native float getAveBytesPerChar(long converterHandle);
-
- /**
- * Gets the number of chars needed for converting a byte
- *
- * @param converterHandle Address of converter object created by the native code
- * @return number of bytes needed
- * @internal ICU 2.4
- */
- public static final native int getMaxCharsPerByte(long converterHandle);
-
- /**
- * Gets the average numnber of chars needed for converting a byte
- *
- * @param converterHandle Address of converter object created by the native code
- * @return number of bytes needed
- * @internal ICU 2.4
- */
- public static final native float getAveCharsPerByte(long converterHandle);
-
- //CSDL: added by Jack
- /**
- * Determines whether charset1 contains charset2.
- */
- public static final native boolean contains(long converterHandle1, long converterHandle2);
-
- public static final native byte[] getSubstitutionBytes(long converterHandle);
-
- /**
- * Ascertains if a given Unicode code unit can
- * be converted to the target encoding
- * @param converterHandle Address of converter object created by the native code
- * @param codeUnit the character to be converted
- * @return true if a character can be converted
- * @internal ICU 2.4
- *
- */
- public static final native boolean canEncode(long converterHandle,int codeUnit);
-
- /**
- * Ascertains if a given a byte sequence can be converted to Unicode
- * @param converterHandle Address of converter object created by the native code
- * @param bytes the bytes to be converted
- * @return true if a character can be converted
- * @internal ICU 2.4
- *
*/
- public static final native boolean canDecode(long converterHandle,byte[] bytes);
-
- /**
- * Gets the canonical names of available converters
- * @return Object[] names as an object array
- * @internal ICU 2.4
- */
- public static final native String[] getAvailable();
+ public static native int flushByteToChar(long converterHandle, char[] output, int outEnd, int[] data);
- public static final native Charset charsetForName(String charsetName);
+ public static native long openConverter(String encoding);
+ public static native void closeConverter(long converterHandle);
+
+ public static native void resetByteToChar(long converterHandle);
+ public static native void resetCharToByte(long converterHandle);
+
+ public static native int setSubstitutionChars(long converterHandle, char[] subChars,int length);
+ public static native int setSubstitutionBytes(long converterHandle, byte[] subChars,int length);
+ public static native byte[] getSubstitutionBytes(long converterHandle);
+
+ public static native int getMaxBytesPerChar(long converterHandle);
+ public static native int getMinBytesPerChar(long converterHandle);
+ public static native float getAveBytesPerChar(long converterHandle);
+ public static native int getMaxCharsPerByte(long converterHandle);
+ public static native float getAveCharsPerByte(long converterHandle);
+
+ public static native boolean contains(long converterHandle1, long converterHandle2);
+
+ public static native boolean canEncode(long converterHandle, int codeUnit);
+
+ public static native String[] getAvailableCharsetNames();
+ public static native Charset charsetForName(String charsetName);
- /**
- * Gets the number of aliases for a converter name
- * @param enc encoding name
- * @return number of aliases for the converter
- * @internal ICU 2.4
- */
- public static final native int countAliases(String enc);
-
- /**
- * Gets the aliases associated with the converter name
- * @param enc converter name
- * @return converter names as elements in an object array
- * @internal ICU 2.4
- */
- public static final native String[] getAliases(String enc);
-
- /**
- * Sets the callback to Unicode for ICU conveter. The default behaviour of ICU callback
- * is to call the specified callback function for both illegal and unmapped sequences.
- * @param converterHandle Adress of the converter object created by native code
- * @param mode call back mode to set. This is either STOP_CALLBACK, SKIP_CALLBACK or SUBSTITUE_CALLBACK
- * The converter performs the specified callback when an error occurs
- * @param stopOnIllegal If true sets the alerts the converter callback to stop on an illegal sequence
- * @return int error code returned by ICU
- * @internal ICU 2.4
- */
- public static final native int setCallbackDecode(long converterHandle, int onMalformedInput, int onUnmappableInput, char[] subChars, int length);
-
- /**
- * Sets the callback from Unicode for ICU conveter. The default behaviour of ICU callback
- * is to call the specified callback function for both illegal and unmapped sequences.
- * @param converterHandle Adress of the converter object created by native code
- * @param mode call back mode to set. This is either STOP_CALLBACK, SKIP_CALLBACK or SUBSTITUE_CALLBACK
- * The converter performs the specified callback when an error occurs
- * @param stopOnIllegal If true sets the alerts the converter callback to stop on an illegal sequence
- * @return int error code returned by ICU
- * @internal ICU 2.4
- */
- public static final native int setCallbackEncode(long converterHandle, int onMalformedInput, int onUnmappableInput, byte[] subBytes, int length);
-
- /**
- * Returns a thread safe clone of the converter
- * @internal ICU 2.4
- */
- public static final native long safeClone(long converterHandle);
-
- /** @internal ICU 2.4 */
public static final int STOP_CALLBACK = 0;//CodingErrorAction.REPORT
- /** @internal ICU 2.4 */
public static final int SKIP_CALLBACK = 1;//CodingErrorAction.IGNORE
- /** @internal ICU 2.4 */
public static final int SUBSTITUTE_CALLBACK = 2;//CodingErrorAction.REPLACE
+ public static native int setCallbackDecode(long converterHandle, int onMalformedInput, int onUnmappableInput, char[] subChars, int length);
+ public static native int setCallbackEncode(long converterHandle, int onMalformedInput, int onUnmappableInput, byte[] subBytes, int length);
}
diff --git a/icu/src/main/native/NativeConverter.cpp b/icu/src/main/native/NativeConverter.cpp
index ebb035f..1bb9ac8 100644
--- a/icu/src/main/native/NativeConverter.cpp
+++ b/icu/src/main/native/NativeConverter.cpp
@@ -15,15 +15,16 @@
* @author: Ram Viswanadha
*/
-#include "JNIHelp.h"
#include "AndroidSystemNatives.h"
-#include "ScopedUtfChars.h"
-#include "unicode/utypes.h" /* Basic ICU data types */
-#include "unicode/ucnv.h" /* C Converter API */
-#include "unicode/ustring.h" /* some more string functions*/
-#include "unicode/ucnv_cb.h" /* for callback functions */
-#include "unicode/uset.h" /* for contains function */
#include "ErrorCode.h"
+#include "JNIHelp.h"
+#include "ScopedUtfChars.h"
+#include "UniquePtr.h"
+#include "unicode/ucnv.h"
+#include "unicode/ucnv_cb.h"
+#include "unicode/uset.h"
+#include "unicode/ustring.h"
+#include "unicode/utypes.h"
#include <stdlib.h>
#include <string.h>
@@ -74,92 +75,6 @@ static void closeConverter(JNIEnv* env, jclass, jlong handle) {
}
/**
- * Sets the substution mode for from Unicode conversion. Currently only
- * two modes are supported: substitute or report
- * @param env environment handle for JNI
- * @param jClass handle for the class
- * @param handle address of ICU converter
- * @param mode the mode to set
- */
-static jint setSubstitutionModeCharToByte (JNIEnv *env, jclass, jlong handle, jboolean mode) {
-
- UConverter* conv = (UConverter*)(long)handle;
- UErrorCode errorCode =U_ZERO_ERROR;
-
- if(conv) {
-
- UConverterFromUCallback fromUOldAction ;
- void* fromUOldContext;
- void* fromUNewContext=NULL;
- if(mode) {
-
- ucnv_setFromUCallBack(conv,
- UCNV_FROM_U_CALLBACK_SUBSTITUTE,
- fromUNewContext,
- &fromUOldAction,
- (const void**)&fromUOldContext,
- &errorCode);
-
- }
- else{
-
- ucnv_setFromUCallBack(conv,
- UCNV_FROM_U_CALLBACK_STOP,
- fromUNewContext,
- &fromUOldAction,
- (const void**)&fromUOldContext,
- &errorCode);
-
- }
- return errorCode;
- }
- errorCode = U_ILLEGAL_ARGUMENT_ERROR;
- return errorCode;
-}
-/**
- * Sets the substution mode for to Unicode conversion. Currently only
- * two modes are supported: substitute or report
- * @param env environment handle for JNI
- * @param jClass handle for the class
- * @param handle address of ICU converter
- * @param mode the mode to set
- */
-static jint setSubstitutionModeByteToChar (JNIEnv *env, jclass, jlong handle, jboolean mode) {
-
- UConverter* conv = (UConverter*)handle;
- UErrorCode errorCode =U_ZERO_ERROR;
-
- if(conv) {
-
- UConverterToUCallback toUOldAction ;
- void* toUOldContext;
- void* toUNewContext=NULL;
- if(mode) {
-
- ucnv_setToUCallBack(conv,
- UCNV_TO_U_CALLBACK_SUBSTITUTE,
- toUNewContext,
- &toUOldAction,
- (const void**)&toUOldContext,
- &errorCode);
-
- }
- else{
-
- ucnv_setToUCallBack(conv,
- UCNV_TO_U_CALLBACK_STOP,
- toUNewContext,
- &toUOldAction,
- (const void**)&toUOldContext,
- &errorCode);
-
- }
- return errorCode;
- }
- errorCode = U_ILLEGAL_ARGUMENT_ERROR;
- return errorCode;
-}
-/**
* Converts a buffer of Unicode code units to target encoding
* @param env environment handle for JNI
* @param jClass handle for the class
@@ -342,38 +257,6 @@ static void resetCharToByte(JNIEnv* env, jclass, jlong handle) {
}
}
-static jint countInvalidBytes (JNIEnv *env, jclass, jlong handle, jintArray length) {
- UConverter* cnv = (UConverter*)handle;
- if (!cnv) {
- return U_ILLEGAL_ARGUMENT_ERROR;
- }
-
- UErrorCode errorCode = U_ZERO_ERROR;
- jint* len = (jint*) env->GetPrimitiveArrayCritical(length, NULL);
- if (len) {
- char invalidChars[32];
- ucnv_getInvalidChars(cnv,invalidChars,(int8_t*)len,&errorCode);
- }
- env->ReleasePrimitiveArrayCritical(length,(jint*)len,0);
- return errorCode;
-}
-
-static jint countInvalidChars(JNIEnv *env, jclass, jlong handle, jintArray length) {
- UConverter* cnv = (UConverter*)handle;
- if (!cnv) {
- return U_ILLEGAL_ARGUMENT_ERROR;
- }
-
- UErrorCode errorCode =U_ZERO_ERROR;
- jint* len = (jint*) env->GetPrimitiveArrayCritical(length, NULL);
- if (len) {
- UChar invalidUChars[32];
- ucnv_getInvalidUChars(cnv,invalidUChars,(int8_t*)len,&errorCode);
- }
- env->ReleasePrimitiveArrayCritical(length,(jint*)len,0);
- return errorCode;
-}
-
static jint getMaxBytesPerChar(JNIEnv *env, jclass, jlong handle) {
UConverter* cnv = (UConverter*)handle;
return (cnv != NULL) ? ucnv_getMaxCharSize(cnv) : -1;
@@ -477,30 +360,26 @@ static jint flushCharToByte (JNIEnv *env, jclass, jlong handle, jbyteArray targe
}
static void toChars(const UChar* us, char* cs, int32_t length) {
- UChar u;
- while(length>0) {
- u=*us++;
+ while (length > 0) {
+ UChar u = *us++;
*cs++=(char)u;
--length;
}
}
static jint setSubstitutionBytes(JNIEnv *env, jclass, jlong handle, jbyteArray subChars, jint length) {
-
UConverter* cnv = (UConverter*) handle;
UErrorCode errorCode = U_ZERO_ERROR;
- if(cnv) {
+ if (cnv) {
jbyte* u_subChars = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(subChars, NULL));
- if(u_subChars) {
- char* mySubChars = new char[length];
- toChars((UChar*)u_subChars,&mySubChars[0],length);
- ucnv_setSubstChars(cnv,mySubChars, (char)length,&errorCode);
- if(U_FAILURE(errorCode)) {
+ if (u_subChars) {
+ char mySubChars[length];
+ toChars((UChar*)u_subChars,&mySubChars[0],length);
+ ucnv_setSubstChars(cnv,mySubChars, (char)length,&errorCode);
+ if(U_FAILURE(errorCode)) {
env->ReleasePrimitiveArrayCritical(subChars,mySubChars,0);
return errorCode;
- }
- delete[] mySubChars;
- }
- else{
+ }
+ } else{
errorCode = U_ILLEGAL_ARGUMENT_ERROR;
}
env->ReleasePrimitiveArrayCritical(subChars,u_subChars,0);
@@ -630,128 +509,53 @@ static jboolean canEncode(JNIEnv *env, jclass, jlong handle, jint codeUnit) {
return (jboolean)FALSE;
}
+/*
+ * If a charset listed in the IANA Charset Registry is supported by an implementation
+ * of the Java platform then its canonical name must be the name listed in the registry.
+ * Many charsets are given more than one name in the registry, in which case the registry
+ * identifies one of the names as MIME-preferred. If a charset has more than one registry
+ * name then its canonical name must be the MIME-preferred name and the other names in
+ * the registry must be valid aliases. If a supported charset is not listed in the IANA
+ * registry then its canonical name must begin with one of the strings "X-" or "x-".
+ */
+static jstring getJavaCanonicalName(JNIEnv *env, const char* icuCanonicalName) {
+ UErrorCode status = U_ZERO_ERROR;
-static jboolean canDecode(JNIEnv *env, jclass, jlong handle, jbyteArray source) {
-
- UErrorCode errorCode =U_ZERO_ERROR;
- UConverter* cnv = (UConverter*)handle;
- if(cnv) {
- jint len = env->GetArrayLength(source);
- jbyte* cSource =(jbyte*) env->GetPrimitiveArrayCritical(source, NULL);
- if(cSource) {
- const char* cSourceLimit = reinterpret_cast<const char*>(cSource+len);
-
- /* Assume that we need at most twice the length of source */
- UChar* target = (UChar*) malloc(sizeof(UChar)* (len<<1));
- UChar* targetLimit = target + (len<<1);
- if(target) {
- ucnv_toUnicode(cnv,&target,targetLimit, (const char**)&cSource,
- cSourceLimit,NULL, TRUE,&errorCode);
-
- if(U_SUCCESS(errorCode)) {
- free(target);
- env->ReleasePrimitiveArrayCritical(source,cSource,0);
- return (jboolean)TRUE;
- }
- }
- free(target);
- }
- env->ReleasePrimitiveArrayCritical(source,cSource,0);
- }
- return (jboolean)FALSE;
-}
-
-static int32_t copyString(char* dest, int32_t destCapacity, int32_t startIndex,
- const char* src, UErrorCode* status) {
- int32_t srcLen = 0, i=0;
- if(U_FAILURE(*status)) {
- return 0;
- }
- if(dest == NULL || src == NULL || destCapacity < startIndex) {
- *status = U_ILLEGAL_ARGUMENT_ERROR;
- return 0;
- }
- srcLen = strlen(src);
- if(srcLen >= destCapacity) {
- *status = U_BUFFER_OVERFLOW_ERROR;
- return 0;
- }
- for(i=0; i < srcLen; i++) {
- dest[startIndex++] = src[i];
- }
- /* null terminate the buffer */
- dest[startIndex] = 0; /* no bounds check already made sure that we have enough room */
- return startIndex;
-}
-
-static int32_t getJavaCanonicalName1(const char* icuCanonicalName,
- char* canonicalName, int32_t capacity,
- UErrorCode* status) {
- int32_t retLen = 0;
+ // Check to see if this is a well-known MIME or IANA name.
const char* cName = NULL;
- /* find out the alias with MIME tag */
- if((cName =ucnv_getStandardName(icuCanonicalName, "MIME", status)) != NULL) {
- retLen = copyString(canonicalName, capacity, 0, cName, status);
- /* find out the alias with IANA tag */
- }else if((cName =ucnv_getStandardName(icuCanonicalName, "IANA", status)) != NULL) {
- retLen = copyString(canonicalName, capacity, 0, cName, status);
- }else {
- /*
- check to see if an alias already exists with x- prefix, if yes then
- make that the canonical name
- */
- int32_t aliasCount = ucnv_countAliases(icuCanonicalName,status);
- int32_t i=0;
- const char* name;
- for(i=0;i<aliasCount;i++) {
- name = ucnv_getAlias(icuCanonicalName,(uint16_t)i, status);
- if(name != NULL && name[0]=='x' && name[1]=='-') {
- retLen = copyString(canonicalName, capacity, 0, name, status);
- break;
- }
- }
- /* last resort just append x- to any of the alias and
- make it the canonical name */
- if(retLen == 0 && U_SUCCESS(*status)) {
- name = ucnv_getStandardName(icuCanonicalName, "UTR22", status);
- if(name == NULL && strchr(icuCanonicalName, ',')!= NULL) {
- name = ucnv_getAlias(icuCanonicalName, 1, status);
- if(*status == U_INDEX_OUTOFBOUNDS_ERROR) {
- *status = U_ZERO_ERROR;
- }
- }
- /* if there is no UTR22 canonical name .. then just return itself*/
- if(name == NULL) {
- name = icuCanonicalName;
- }
- if(capacity >= 2) {
- strcpy(canonicalName,"x-");
- }
- retLen = copyString(canonicalName, capacity, 2, name, status);
+ if ((cName = ucnv_getStandardName(icuCanonicalName, "MIME", &status)) != NULL) {
+ return env->NewStringUTF(cName);
+ } else if ((cName = ucnv_getStandardName(icuCanonicalName, "IANA", &status)) != NULL) {
+ return env->NewStringUTF(cName);
+ }
+
+ // Check to see if an alias already exists with "x-" prefix, if yes then
+ // make that the canonical name.
+ int32_t aliasCount = ucnv_countAliases(icuCanonicalName, &status);
+ for (int i = 0; i < aliasCount; ++i) {
+ const char* name = ucnv_getAlias(icuCanonicalName, i, &status);
+ if (name != NULL && name[0] == 'x' && name[1] == '-') {
+ return env->NewStringUTF(name);
}
}
- return retLen;
-}
-static jstring getJavaCanonicalName(JNIEnv *env, const char* icuCanonicalName) {
- /*
- * If a charset listed in the IANA Charset Registry is supported by an implementation
- * of the Java platform then its canonical name must be the name listed in the registry.
- * Many charsets are given more than one name in the registry, in which case the registry
- * identifies one of the names as MIME-preferred. If a charset has more than one registry
- * name then its canonical name must be the MIME-preferred name and the other names in
- * the registry must be valid aliases. If a supported charset is not listed in the IANA
- * registry then its canonical name must begin with one of the strings "X-" or "x-".
- */
- UErrorCode error = U_ZERO_ERROR;
- char cName[UCNV_MAX_CONVERTER_NAME_LENGTH] = {0};
- if (icuCanonicalName[0] != 0) {
- getJavaCanonicalName1(icuCanonicalName, cName, UCNV_MAX_CONVERTER_NAME_LENGTH, &error);
+ // As a last resort, prepend "x-" to any alias and make that the canonical name.
+ status = U_ZERO_ERROR;
+ const char* name = ucnv_getStandardName(icuCanonicalName, "UTR22", &status);
+ if (name == NULL && strchr(icuCanonicalName, ',') != NULL) {
+ name = ucnv_getAlias(icuCanonicalName, 1, &status);
}
- return env->NewStringUTF(cName);
+ // If there is no UTR22 canonical name then just return the original name.
+ if (name == NULL) {
+ name = icuCanonicalName;
+ }
+ UniquePtr<char[]> result(new char[2 + strlen(name) + 1]);
+ strcpy(&result[0], "x-");
+ strcat(&result[0], name);
+ return env->NewStringUTF(&result[0]);
}
-static jobjectArray getAvailable(JNIEnv *env, jclass) {
+static jobjectArray getAvailableCharsetNames(JNIEnv *env, jclass) {
int32_t num = ucnv_countAvailable();
jobjectArray result = env->NewObjectArray(num, env->FindClass("java/lang/String"), NULL);
for (int i = 0; i < num; ++i) {
@@ -763,12 +567,6 @@ static jobjectArray getAvailable(JNIEnv *env, jclass) {
return result;
}
-static jint countAliases(JNIEnv *env, jclass, jstring enc) {
- ScopedUtfChars encChars(env, enc);
- UErrorCode error = U_ZERO_ERROR;
- return encChars.data() ? ucnv_countAliases(encChars.data(), &error) : 0;
-}
-
static jobjectArray getAliases(JNIEnv* env, const char* icuCanonicalName) {
// Get an upper bound on the number of aliases...
const char* myEncName = icuCanonicalName;
@@ -872,10 +670,11 @@ static void CHARSET_ENCODER_CALLBACK(const void *context,
*status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
- if(realCB==NULL) {
+ if (realCB == NULL) {
*status = U_INTERNAL_PROGRAM_ERROR;
+ } else {
+ realCB(context, fromArgs, codeUnits, length, codePoint, reason, status);
}
- realCB(context, fromArgs, codeUnits, length, codePoint, reason, status);
}
}
}
@@ -1027,10 +826,11 @@ static void CHARSET_DECODER_CALLBACK(const void *context,
*status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
- if(realCB==NULL) {
+ if (realCB == NULL) {
*status = U_INTERNAL_PROGRAM_ERROR;
+ } else {
+ realCB(context, args, codeUnits, length, reason, status);
}
- realCB(context, args, codeUnits, length, reason, status);
}
}
}
@@ -1085,18 +885,6 @@ static jint setCallbackDecode(JNIEnv *env, jclass, jlong handle, jint onMalforme
return U_ILLEGAL_ARGUMENT_ERROR;
}
-static jlong safeClone(JNIEnv *env, jclass, jlong address) {
- UConverter* source = reinterpret_cast<UConverter*>(static_cast<uintptr_t>(address));
- if (!source) {
- return NULL;
- }
- UErrorCode status = U_ZERO_ERROR;
- jint bufferSize = U_CNV_SAFECLONE_BUFFERSIZE;
- UConverter* conv = ucnv_safeClone(source, NULL, &bufferSize, &status);
- icu4jni_error(env, status);
- return reinterpret_cast<uintptr_t>(conv);
-}
-
static jint getMaxCharsPerByte(JNIEnv *env, jclass, jlong handle) {
/*
* currently we know that max number of chars per byte is 2
@@ -1204,37 +992,28 @@ static jobject charsetForName(JNIEnv* env, jclass, jstring charsetName) {
*/
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
+ { "canEncode", "(JI)Z", (void*) canEncode },
{ "charsetForName", "(Ljava/lang/String;)Ljava/nio/charset/Charset;", (void*) charsetForName },
- { "convertByteToChar", "(J[BI[CI[IZ)I", (void*) convertByteToChar },
+ { "closeConverter", "(J)V", (void*) closeConverter },
+ { "contains", "(JJ)Z", (void*) contains },
{ "decode", "(J[BI[CI[IZ)I", (void*) decode },
- { "convertCharToByte", "(J[CI[BI[IZ)I", (void*) convertCharToByte },
{ "encode", "(J[CI[BI[IZ)I", (void*) encode },
- { "flushCharToByte", "(J[BI[I)I", (void*) flushCharToByte },
{ "flushByteToChar", "(J[CI[I)I", (void*) flushByteToChar },
- { "openConverter", "(Ljava/lang/String;)J", (void*) openConverter },
- { "resetByteToChar", "(J)V", (void*) resetByteToChar },
- { "resetCharToByte", "(J)V", (void*) resetCharToByte },
- { "closeConverter", "(J)V", (void*) closeConverter },
- { "setSubstitutionChars", "(J[CI)I", (void*) setSubstitutionChars },
- { "setSubstitutionBytes", "(J[BI)I", (void*) setSubstitutionBytes },
- { "setSubstitutionModeCharToByte", "(JZ)I", (void*) setSubstitutionModeCharToByte },
- { "setSubstitutionModeByteToChar", "(JZ)I", (void*) setSubstitutionModeByteToChar },
- { "countInvalidBytes", "(J[I)I", (void*) countInvalidBytes },
- { "countInvalidChars", "(J[I)I", (void*) countInvalidChars },
- { "getMaxBytesPerChar", "(J)I", (void*) getMaxBytesPerChar },
- { "getMinBytesPerChar", "(J)I", (void*) getMinBytesPerChar },
+ { "flushCharToByte", "(J[BI[I)I", (void*) flushCharToByte },
+ { "getAvailableCharsetNames", "()[Ljava/lang/String;", (void*) getAvailableCharsetNames },
{ "getAveBytesPerChar", "(J)F", (void*) getAveBytesPerChar },
- { "getMaxCharsPerByte", "(J)I", (void*) getMaxCharsPerByte },
{ "getAveCharsPerByte", "(J)F", (void*) getAveCharsPerByte },
- { "contains", "(JJ)Z", (void*) contains },
+ { "getMaxBytesPerChar", "(J)I", (void*) getMaxBytesPerChar },
+ { "getMaxCharsPerByte", "(J)I", (void*) getMaxCharsPerByte },
+ { "getMinBytesPerChar", "(J)I", (void*) getMinBytesPerChar },
{ "getSubstitutionBytes", "(J)[B", (void*) getSubstitutionBytes },
- { "canEncode", "(JI)Z", (void*) canEncode },
- { "canDecode", "(J[B)Z", (void*) canDecode },
- { "getAvailable", "()[Ljava/lang/String;", (void*) getAvailable },
- { "countAliases", "(Ljava/lang/String;)I", (void*) countAliases },
+ { "openConverter", "(Ljava/lang/String;)J", (void*) openConverter },
+ { "resetByteToChar", "(J)V", (void*) resetByteToChar },
+ { "resetCharToByte", "(J)V", (void*) resetCharToByte },
{ "setCallbackDecode", "(JII[CI)I", (void*) setCallbackDecode },
{ "setCallbackEncode", "(JII[BI)I", (void*) setCallbackEncode },
- { "safeClone", "(J)J", (void*) safeClone }
+ { "setSubstitutionBytes", "(J[BI)I", (void*) setSubstitutionBytes },
+ { "setSubstitutionChars", "(J[CI)I", (void*) setSubstitutionChars },
};
int register_com_ibm_icu4jni_converters_NativeConverter(JNIEnv *_env) {