1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project******************************************************************************* 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project* Copyright (C) 1996-2006, International Business Machines Corporation and * 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project* others. All Rights Reserved. * 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project******************************************************************************* 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project* 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project* 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project******************************************************************************* 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project*/ 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (C) Copyright IBM Corp. 2000 - All Rights Reserved 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A JNI wrapper to ICU native converter Interface 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @author: Ram Viswanadha 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 16757a7942eed2b0aa457f8517a0259d2ac82c5b18Elliott Hughes#define LOG_TAG "NativeConverter" 17757a7942eed2b0aa457f8517a0259d2ac82c5b18Elliott Hughes 183aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes#include "IcuUtilities.h" 19ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes#include "JNIHelp.h" 20a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes#include "JniConstants.h" 21bef9ec33e1368f57c731fce63b6a8c61628c64b0Elliott Hughes#include "JniException.h" 228044bf6b446c93cd29c5753544246316f269064fElliott Hughes#include "ScopedLocalRef.h" 23cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes#include "ScopedPrimitiveArray.h" 2437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes#include "ScopedStringChars.h" 25ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes#include "ScopedUtfChars.h" 26cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes#include "cutils/log.h" 27ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes#include "toStringArray.h" 28ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes#include "unicode/ucnv.h" 29ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes#include "unicode/ucnv_cb.h" 307d52d787302b862019da41aa753646d88d43fd61Elliott Hughes#include "unicode/uniset.h" 31ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes#include "unicode/ustring.h" 32ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes#include "unicode/utypes.h" 33ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes 34b3aacde3d8af759ee4a7b395c636ea360547d92dIan Rogers#include <memory> 35ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes#include <vector> 36ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <stdlib.h> 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <string.h> 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 40c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes#define NativeConverter_REPORT 0 41c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes#define NativeConverter_IGNORE 1 42c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes#define NativeConverter_REPLACE 2 434722f161d49b5c483aa7aec0daad7bfee18578bbElliott Hughes 4437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes#define MAX_REPLACEMENT_LENGTH 32 // equivalent to UCNV_ERROR_BUFFER_LENGTH 4537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes 46cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughesstruct DecoderCallbackContext { 4737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes UChar replacementChars[MAX_REPLACEMENT_LENGTH]; 4837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes size_t replacementCharCount; 49cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UConverterToUCallback onUnmappableInput; 50cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UConverterToUCallback onMalformedInput; 51cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes}; 52cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes 53cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughesstruct EncoderCallbackContext { 5437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes char replacementBytes[MAX_REPLACEMENT_LENGTH]; 5537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes size_t replacementByteCount; 56cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UConverterFromUCallback onUnmappableInput; 57cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UConverterFromUCallback onMalformedInput; 58cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes}; 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 60ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughesstatic UConverter* toUConverter(jlong address) { 61ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes return reinterpret_cast<UConverter*>(static_cast<uintptr_t>(address)); 62ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes} 63ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes 64783a57a7ece339bc246925e328bc82b50cae427aElliott Hughesstatic bool collectStandardNames(JNIEnv* env, const char* canonicalName, const char* standard, 65783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes std::vector<std::string>& result) { 66783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes UErrorCode status = U_ZERO_ERROR; 67a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UStringEnumeration e(ucnv_openStandardNames(canonicalName, standard, &status)); 68783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes if (maybeThrowIcuException(env, "ucnv_openStandardNames", status)) { 69783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes return false; 70ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 71783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes 72783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes int32_t count = e.count(status); 73783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes if (maybeThrowIcuException(env, "StringEnumeration::count", status)) { 74783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes return false; 75ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 76ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes 77783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes for (int32_t i = 0; i < count; ++i) { 78a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* string = e.snext(status); 79783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes if (maybeThrowIcuException(env, "StringEnumeration::snext", status)) { 80783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes return false; 81ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 82783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes std::string s; 83783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes string->toUTF8String(s); 84783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes if (s.find_first_of("+,") == std::string::npos) { 85783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes result.push_back(s); 86ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 87ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 88783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes 89783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes return true; 90ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes} 91ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes 92ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughesstatic const char* getICUCanonicalName(const char* name) { 93ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes UErrorCode error = U_ZERO_ERROR; 94ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes const char* canonicalName = NULL; 95ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes if ((canonicalName = ucnv_getCanonicalName(name, "MIME", &error)) != NULL) { 96ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes return canonicalName; 97ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } else if ((canonicalName = ucnv_getCanonicalName(name, "IANA", &error)) != NULL) { 98ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes return canonicalName; 99ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } else if ((canonicalName = ucnv_getCanonicalName(name, "", &error)) != NULL) { 100ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes return canonicalName; 101ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } else if ((canonicalName = ucnv_getAlias(name, 0, &error)) != NULL) { 102ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes // We have some aliases in the form x-blah .. match those first. 103ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes return canonicalName; 104ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } else if (strstr(name, "x-") == name) { 105ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes // Check if the converter can be opened with the name given. 106ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes error = U_ZERO_ERROR; 107a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::LocalUConverterPointer cnv(ucnv_open(name + 2, &error)); 108ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes if (U_SUCCESS(error)) { 109ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes return name + 2; 110ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 111ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 112ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes return NULL; 113ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes} 114ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes 115ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes// If a charset listed in the IANA Charset Registry is supported by an implementation 116ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes// of the Java platform then its canonical name must be the name listed in the registry. 117ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes// Many charsets are given more than one name in the registry, in which case the registry 118ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes// identifies one of the names as MIME-preferred. If a charset has more than one registry 119ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes// name then its canonical name must be the MIME-preferred name and the other names in 120ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes// the registry must be valid aliases. If a supported charset is not listed in the IANA 121ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes// registry then its canonical name must begin with one of the strings "X-" or "x-". 122ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughesstatic jstring getJavaCanonicalName(JNIEnv* env, const char* icuCanonicalName) { 123ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes UErrorCode status = U_ZERO_ERROR; 124ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes 125ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes // Check to see if this is a well-known MIME or IANA name. 126ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes const char* cName = NULL; 127ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes if ((cName = ucnv_getStandardName(icuCanonicalName, "MIME", &status)) != NULL) { 128ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes return env->NewStringUTF(cName); 129ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } else if ((cName = ucnv_getStandardName(icuCanonicalName, "IANA", &status)) != NULL) { 130ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes return env->NewStringUTF(cName); 131ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 132ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes 133ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes // Check to see if an alias already exists with "x-" prefix, if yes then 134ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes // make that the canonical name. 135ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes int32_t aliasCount = ucnv_countAliases(icuCanonicalName, &status); 136ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes for (int i = 0; i < aliasCount; ++i) { 137ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes const char* name = ucnv_getAlias(icuCanonicalName, i, &status); 138ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes if (name != NULL && name[0] == 'x' && name[1] == '-') { 139ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes return env->NewStringUTF(name); 140ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 141ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 142ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes 143ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes // As a last resort, prepend "x-" to any alias and make that the canonical name. 144ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes status = U_ZERO_ERROR; 145ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes const char* name = ucnv_getStandardName(icuCanonicalName, "UTR22", &status); 146ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes if (name == NULL && strchr(icuCanonicalName, ',') != NULL) { 147ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes name = ucnv_getAlias(icuCanonicalName, 1, &status); 148ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 149ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes // If there is no UTR22 canonical name then just return the original name. 150ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes if (name == NULL) { 151ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes name = icuCanonicalName; 152ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 153b3aacde3d8af759ee4a7b395c636ea360547d92dIan Rogers std::unique_ptr<char[]> result(new char[2 + strlen(name) + 1]); 154ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes strcpy(&result[0], "x-"); 155ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes strcat(&result[0], name); 156ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes return env->NewStringUTF(&result[0]); 157ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes} 158ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes 1597d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic jlong NativeConverter_openConverter(JNIEnv* env, jclass, jstring converterName) { 160bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes ScopedUtfChars converterNameChars(env, converterName); 16105960876dff6a5b686821eed8f7ae7cef5af4f50Elliott Hughes if (converterNameChars.c_str() == NULL) { 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 0; 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 164bef9ec33e1368f57c731fce63b6a8c61628c64b0Elliott Hughes UErrorCode status = U_ZERO_ERROR; 165bef9ec33e1368f57c731fce63b6a8c61628c64b0Elliott Hughes UConverter* cnv = ucnv_open(converterNameChars.c_str(), &status); 1665ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "ucnv_open", status); 167ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes return reinterpret_cast<uintptr_t>(cnv); 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1707d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic void NativeConverter_closeConverter(JNIEnv*, jclass, jlong address) { 1719b4866d3438f42fb2c0df788989261afe72bf713Elliott Hughes ucnv_close(toUConverter(address)); 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1745ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughesstatic bool shouldCodecThrow(jboolean flush, UErrorCode error) { 1755ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes if (flush) { 1765ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes return (error != U_BUFFER_OVERFLOW_ERROR && error != U_TRUNCATED_CHAR_FOUND); 1775ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes } else { 1785ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes return (error != U_BUFFER_OVERFLOW_ERROR && error != U_INVALID_CHAR_FOUND && error != U_ILLEGAL_CHAR_FOUND); 1795ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes } 1805ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes} 1815ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes 1827d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic jint NativeConverter_encode(JNIEnv* env, jclass, jlong address, 1837d52d787302b862019da41aa753646d88d43fd61Elliott Hughes jcharArray source, jint sourceEnd, jbyteArray target, jint targetEnd, 1847d52d787302b862019da41aa753646d88d43fd61Elliott Hughes jintArray data, jboolean flush) { 1857d52d787302b862019da41aa753646d88d43fd61Elliott Hughes 186ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UConverter* cnv = toUConverter(address); 18764101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes if (cnv == NULL) { 1885ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "toUConverter", U_ILLEGAL_ARGUMENT_ERROR); 18964101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes return U_ILLEGAL_ARGUMENT_ERROR; 19064101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes } 191ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes ScopedCharArrayRO uSource(env, source); 19264101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes if (uSource.get() == NULL) { 1935ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "uSource", U_ILLEGAL_ARGUMENT_ERROR); 19464101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes return U_ILLEGAL_ARGUMENT_ERROR; 19564101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes } 196ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes ScopedByteArrayRW uTarget(env, target); 19764101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes if (uTarget.get() == NULL) { 1985ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "uTarget", U_ILLEGAL_ARGUMENT_ERROR); 19964101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes return U_ILLEGAL_ARGUMENT_ERROR; 20064101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes } 201ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes ScopedIntArrayRW myData(env, data); 20264101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes if (myData.get() == NULL) { 2035ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "myData", U_ILLEGAL_ARGUMENT_ERROR); 20499c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes return U_ILLEGAL_ARGUMENT_ERROR; 20599c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes } 206ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes 207ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes // Do the conversion. 208ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes jint* sourceOffset = &myData[0]; 209ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes jint* targetOffset = &myData[1]; 210ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes const jchar* mySource = uSource.get() + *sourceOffset; 211ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes const UChar* mySourceLimit= uSource.get() + sourceEnd; 212ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes char* cTarget = reinterpret_cast<char*>(uTarget.get() + *targetOffset); 213ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes const char* cTargetLimit = reinterpret_cast<const char*>(uTarget.get() + targetEnd); 21499c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes UErrorCode errorCode = U_ZERO_ERROR; 215ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes ucnv_fromUnicode(cnv , &cTarget, cTargetLimit, &mySource, mySourceLimit, NULL, (UBool) flush, &errorCode); 216ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes *sourceOffset = (mySource - uSource.get()) - *sourceOffset; 2174e4b93ffe988b0a597835d852489573b57e0f3feNarayan Kamath *targetOffset = (reinterpret_cast<jbyte*>(cTarget) - uTarget.get()); 218ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes 219ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes // If there was an error, count the problematic characters. 220f15b280ac1c2e32f7becdb314440c2999dc8d204Narayan Kamath if (errorCode == U_ILLEGAL_CHAR_FOUND || errorCode == U_INVALID_CHAR_FOUND || 221f15b280ac1c2e32f7becdb314440c2999dc8d204Narayan Kamath errorCode == U_TRUNCATED_CHAR_FOUND) { 2222981b5e8cf7c19dfd85b2088b18b7a6146825317Elliott Hughes int8_t invalidUCharCount = 32; 223ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UChar invalidUChars[32]; 22433604713c5c70f9e6cad61dee6eb628db666bb22Elliott Hughes UErrorCode minorErrorCode = U_ZERO_ERROR; 2252981b5e8cf7c19dfd85b2088b18b7a6146825317Elliott Hughes ucnv_getInvalidUChars(cnv, invalidUChars, &invalidUCharCount, &minorErrorCode); 226ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes if (U_SUCCESS(minorErrorCode)) { 2272981b5e8cf7c19dfd85b2088b18b7a6146825317Elliott Hughes myData[2] = invalidUCharCount; 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2305ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes 2315ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes // Managed code handles some cases; throw all other errors. 2325ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes if (shouldCodecThrow(flush, errorCode)) { 2335ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "ucnv_fromUnicode", errorCode); 2345ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes } 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return errorCode; 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2387d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic jint NativeConverter_decode(JNIEnv* env, jclass, jlong address, 2397d52d787302b862019da41aa753646d88d43fd61Elliott Hughes jbyteArray source, jint sourceEnd, jcharArray target, jint targetEnd, 2407d52d787302b862019da41aa753646d88d43fd61Elliott Hughes jintArray data, jboolean flush) { 2417d52d787302b862019da41aa753646d88d43fd61Elliott Hughes 242ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UConverter* cnv = toUConverter(address); 24364101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes if (cnv == NULL) { 2445ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "toUConverter", U_ILLEGAL_ARGUMENT_ERROR); 24564101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes return U_ILLEGAL_ARGUMENT_ERROR; 24664101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes } 247ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes ScopedByteArrayRO uSource(env, source); 24864101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes if (uSource.get() == NULL) { 2495ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "uSource", U_ILLEGAL_ARGUMENT_ERROR); 25064101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes return U_ILLEGAL_ARGUMENT_ERROR; 25164101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes } 252ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes ScopedCharArrayRW uTarget(env, target); 25364101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes if (uTarget.get() == NULL) { 2545ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "uTarget", U_ILLEGAL_ARGUMENT_ERROR); 25564101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes return U_ILLEGAL_ARGUMENT_ERROR; 25664101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes } 257ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes ScopedIntArrayRW myData(env, data); 25864101124267c6a0a9a12dc854bdec39cbc506259Elliott Hughes if (myData.get() == NULL) { 2595ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "myData", U_ILLEGAL_ARGUMENT_ERROR); 260ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes return U_ILLEGAL_ARGUMENT_ERROR; 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 263ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes // Do the conversion. 264ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes jint* sourceOffset = &myData[0]; 265ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes jint* targetOffset = &myData[1]; 266583ce47780cae3a014ca46534e08f5c2adc8fa88Elliott Hughes const char* mySource = reinterpret_cast<const char*>(uSource.get() + *sourceOffset); 267ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes const char* mySourceLimit = reinterpret_cast<const char*>(uSource.get() + sourceEnd); 268ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UChar* cTarget = uTarget.get() + *targetOffset; 269ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes const UChar* cTargetLimit = uTarget.get() + targetEnd; 270ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UErrorCode errorCode = U_ZERO_ERROR; 271583ce47780cae3a014ca46534e08f5c2adc8fa88Elliott Hughes ucnv_toUnicode(cnv, &cTarget, cTargetLimit, &mySource, mySourceLimit, NULL, flush, &errorCode); 272583ce47780cae3a014ca46534e08f5c2adc8fa88Elliott Hughes *sourceOffset = mySource - reinterpret_cast<const char*>(uSource.get()) - *sourceOffset; 273ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes *targetOffset = cTarget - uTarget.get() - *targetOffset; 274ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes 275ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes // If there was an error, count the problematic bytes. 276bd024cc687470a008999d96fd3af4a1261413d55Narayan Kamath if (errorCode == U_ILLEGAL_CHAR_FOUND || errorCode == U_INVALID_CHAR_FOUND || 277bd024cc687470a008999d96fd3af4a1261413d55Narayan Kamath errorCode == U_TRUNCATED_CHAR_FOUND) { 2782981b5e8cf7c19dfd85b2088b18b7a6146825317Elliott Hughes int8_t invalidByteCount = 32; 2792981b5e8cf7c19dfd85b2088b18b7a6146825317Elliott Hughes char invalidBytes[32] = {'\0'}; 2802981b5e8cf7c19dfd85b2088b18b7a6146825317Elliott Hughes UErrorCode minorErrorCode = U_ZERO_ERROR; 2812981b5e8cf7c19dfd85b2088b18b7a6146825317Elliott Hughes ucnv_getInvalidChars(cnv, invalidBytes, &invalidByteCount, &minorErrorCode); 282ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes if (U_SUCCESS(minorErrorCode)) { 2832981b5e8cf7c19dfd85b2088b18b7a6146825317Elliott Hughes myData[2] = invalidByteCount; 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2875ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes // Managed code handles some cases; throw all other errors. 2885ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes if (shouldCodecThrow(flush, errorCode)) { 2895ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "ucnv_toUnicode", errorCode); 2905ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes } 291ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes return errorCode; 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2947d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic void NativeConverter_resetByteToChar(JNIEnv*, jclass, jlong address) { 295ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UConverter* cnv = toUConverter(address); 296bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (cnv) { 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ucnv_resetToUnicode(cnv); 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3017d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic void NativeConverter_resetCharToByte(JNIEnv*, jclass, jlong address) { 302ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UConverter* cnv = toUConverter(address); 303bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (cnv) { 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ucnv_resetFromUnicode(cnv); 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3087d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic jint NativeConverter_getMaxBytesPerChar(JNIEnv*, jclass, jlong address) { 309ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UConverter* cnv = toUConverter(address); 310bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return (cnv != NULL) ? ucnv_getMaxCharSize(cnv) : -1; 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3137d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic jint NativeConverter_getMinBytesPerChar(JNIEnv*, jclass, jlong address) { 314ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UConverter* cnv = toUConverter(address); 315bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return (cnv != NULL) ? ucnv_getMinCharSize(cnv) : -1; 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3187d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic jfloat NativeConverter_getAveBytesPerChar(JNIEnv*, jclass, jlong address) { 319ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UConverter* cnv = toUConverter(address); 320c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes return (cnv != NULL) ? ((ucnv_getMaxCharSize(cnv) + ucnv_getMinCharSize(cnv)) / 2.0) : -1; 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 322bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes 3237d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic jobjectArray NativeConverter_getAvailableCharsetNames(JNIEnv* env, jclass) { 324bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes int32_t num = ucnv_countAvailable(); 325a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes jobjectArray result = env->NewObjectArray(num, JniConstants::stringClass, NULL); 326ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes if (result == NULL) { 327ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return NULL; 328ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes } 329bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes for (int i = 0; i < num; ++i) { 330bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes const char* name = ucnv_getAvailableName(i); 3318044bf6b446c93cd29c5753544246316f269064fElliott Hughes ScopedLocalRef<jstring> javaCanonicalName(env, getJavaCanonicalName(env, name)); 332ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes if (javaCanonicalName.get() == NULL) { 333ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return NULL; 334ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes } 3358044bf6b446c93cd29c5753544246316f269064fElliott Hughes env->SetObjectArrayElement(result, i, javaCanonicalName.get()); 336ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes if (env->ExceptionCheck()) { 337ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return NULL; 338ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes } 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 340bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return result; 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 343cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughesstatic void CHARSET_ENCODER_CALLBACK(const void* rawContext, UConverterFromUnicodeArgs* args, 344cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes const UChar* codeUnits, int32_t length, UChar32 codePoint, UConverterCallbackReason reason, 345cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UErrorCode* status) { 346cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes if (!rawContext) { 347cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return; 348cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes } 349cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes const EncoderCallbackContext* ctx = reinterpret_cast<const EncoderCallbackContext*>(rawContext); 350cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes switch(reason) { 351cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes case UCNV_UNASSIGNED: 352cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes ctx->onUnmappableInput(ctx, args, codeUnits, length, codePoint, reason, status); 353cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return; 354cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes case UCNV_ILLEGAL: 355cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes case UCNV_IRREGULAR: 356cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes ctx->onMalformedInput(ctx, args, codeUnits, length, codePoint, reason, status); 357cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return; 3589b4866d3438f42fb2c0df788989261afe72bf713Elliott Hughes case UCNV_CLOSE: 3599b4866d3438f42fb2c0df788989261afe72bf713Elliott Hughes delete ctx; 3609b4866d3438f42fb2c0df788989261afe72bf713Elliott Hughes return; 361cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes default: 362cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes *status = U_ILLEGAL_ARGUMENT_ERROR; 363cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return; 36499c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes } 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 367c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughesstatic void encoderReplaceCallback(const void* rawContext, 368acce5ff29455054faa08a10e1486a156b9d1553eElliott Hughes UConverterFromUnicodeArgs* fromArgs, const UChar*, int32_t, UChar32, 369cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UConverterCallbackReason, UErrorCode * err) { 370cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes if (rawContext == NULL) { 371cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return; 372cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes } 373cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes const EncoderCallbackContext* context = reinterpret_cast<const EncoderCallbackContext*>(rawContext); 374cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes *err = U_ZERO_ERROR; 37537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes ucnv_cbFromUWriteBytes(fromArgs, context->replacementBytes, context->replacementByteCount, 0, err); 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3781698d148fba5718d68de04df1b726940c50fd015Elliott Hughesstatic UConverterFromUCallback getFromUCallback(int32_t mode) { 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project switch(mode) { 3802981b5e8cf7c19dfd85b2088b18b7a6146825317Elliott Hughes case NativeConverter_IGNORE: return UCNV_FROM_U_CALLBACK_SKIP; 3812981b5e8cf7c19dfd85b2088b18b7a6146825317Elliott Hughes case NativeConverter_REPLACE: return encoderReplaceCallback; 3822981b5e8cf7c19dfd85b2088b18b7a6146825317Elliott Hughes case NativeConverter_REPORT: return UCNV_FROM_U_CALLBACK_STOP; 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 384cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes abort(); 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3875ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughesstatic void NativeConverter_setCallbackEncode(JNIEnv* env, jclass, jlong address, 38837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes jint onMalformedInput, jint onUnmappableInput, jbyteArray javaReplacement) { 389ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UConverter* cnv = toUConverter(address); 3905ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes if (cnv == NULL) { 3915ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "toUConverter", U_ILLEGAL_ARGUMENT_ERROR); 3925ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes return; 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 39437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes 39537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes UConverterFromUCallback oldCallback = NULL; 39637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes const void* oldCallbackContext = NULL; 39737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes ucnv_getFromUCallBack(cnv, &oldCallback, const_cast<const void**>(&oldCallbackContext)); 39837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes 39937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes EncoderCallbackContext* callbackContext = const_cast<EncoderCallbackContext*>( 40037871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes reinterpret_cast<const EncoderCallbackContext*>(oldCallbackContext)); 40137871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes if (callbackContext == NULL) { 40237871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes callbackContext = new EncoderCallbackContext; 40337871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes } 40437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes 40537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes callbackContext->onMalformedInput = getFromUCallback(onMalformedInput); 40637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes callbackContext->onUnmappableInput = getFromUCallback(onUnmappableInput); 40737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes 40837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes ScopedByteArrayRO replacementBytes(env, javaReplacement); 40937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes if (replacementBytes.get() == NULL) { 4105ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "replacementBytes", U_ILLEGAL_ARGUMENT_ERROR); 4115ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes return; 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 41337871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes memcpy(callbackContext->replacementBytes, replacementBytes.get(), replacementBytes.size()); 41437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes callbackContext->replacementByteCount = replacementBytes.size(); 41537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes 416cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UErrorCode errorCode = U_ZERO_ERROR; 41737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes ucnv_setFromUCallBack(cnv, CHARSET_ENCODER_CALLBACK, callbackContext, NULL, NULL, &errorCode); 4185ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "ucnv_setFromUCallBack", errorCode); 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 421c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughesstatic void decoderIgnoreCallback(const void*, UConverterToUnicodeArgs*, const char*, int32_t, UConverterCallbackReason, UErrorCode* err) { 422c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // The icu4c UCNV_FROM_U_CALLBACK_SKIP callback requires that the context is NULL, which is 423c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // never true for us. 424c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes *err = U_ZERO_ERROR; 425c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes} 426c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes 427c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughesstatic void decoderReplaceCallback(const void* rawContext, 428cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UConverterToUnicodeArgs* toArgs, const char*, int32_t, UConverterCallbackReason, 429cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UErrorCode* err) { 430cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes if (!rawContext) { 431cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return; 43299c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes } 433cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes const DecoderCallbackContext* context = reinterpret_cast<const DecoderCallbackContext*>(rawContext); 434cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes *err = U_ZERO_ERROR; 43537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes ucnv_cbToUWriteUChars(toArgs,context->replacementChars, context->replacementCharCount, 0, err); 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 438cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughesstatic UConverterToUCallback getToUCallback(int32_t mode) { 439cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes switch (mode) { 440c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes case NativeConverter_IGNORE: return decoderIgnoreCallback; 441c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes case NativeConverter_REPLACE: return decoderReplaceCallback; 442c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes case NativeConverter_REPORT: return UCNV_TO_U_CALLBACK_STOP; 443cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes } 444cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes abort(); 445cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes} 446cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes 447cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughesstatic void CHARSET_DECODER_CALLBACK(const void* rawContext, UConverterToUnicodeArgs* args, 448cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes const char* codeUnits, int32_t length, 449cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UConverterCallbackReason reason, UErrorCode* status) { 450cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes if (!rawContext) { 451cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return; 452cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes } 453cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes const DecoderCallbackContext* ctx = reinterpret_cast<const DecoderCallbackContext*>(rawContext); 454cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes switch(reason) { 455cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes case UCNV_UNASSIGNED: 456cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes ctx->onUnmappableInput(ctx, args, codeUnits, length, reason, status); 457cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return; 458cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes case UCNV_ILLEGAL: 459cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes case UCNV_IRREGULAR: 460cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes ctx->onMalformedInput(ctx, args, codeUnits, length, reason, status); 461cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return; 4629b4866d3438f42fb2c0df788989261afe72bf713Elliott Hughes case UCNV_CLOSE: 4639b4866d3438f42fb2c0df788989261afe72bf713Elliott Hughes delete ctx; 4649b4866d3438f42fb2c0df788989261afe72bf713Elliott Hughes return; 465cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes default: 466cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes *status = U_ILLEGAL_ARGUMENT_ERROR; 467cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return; 468cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes } 469cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes} 470cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes 4715ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughesstatic void NativeConverter_setCallbackDecode(JNIEnv* env, jclass, jlong address, 47237871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes jint onMalformedInput, jint onUnmappableInput, jstring javaReplacement) { 473ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UConverter* cnv = toUConverter(address); 474ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes if (cnv == NULL) { 4755ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "toConverter", U_ILLEGAL_ARGUMENT_ERROR); 4765ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes return; 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 47937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes UConverterToUCallback oldCallback; 48037871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes const void* oldCallbackContext; 48137871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes ucnv_getToUCallBack(cnv, &oldCallback, &oldCallbackContext); 48237871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes 48337871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes DecoderCallbackContext* callbackContext = const_cast<DecoderCallbackContext*>( 48437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes reinterpret_cast<const DecoderCallbackContext*>(oldCallbackContext)); 48537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes if (callbackContext == NULL) { 48637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes callbackContext = new DecoderCallbackContext; 48737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes } 48837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes 48937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes callbackContext->onMalformedInput = getToUCallback(onMalformedInput); 49037871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes callbackContext->onUnmappableInput = getToUCallback(onUnmappableInput); 49137871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes 49237871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes ScopedStringChars replacement(env, javaReplacement); 49337871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes if (replacement.get() == NULL) { 4945ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "replacement", U_ILLEGAL_ARGUMENT_ERROR); 4955ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes return; 496cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes } 49737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes u_strncpy(callbackContext->replacementChars, replacement.get(), replacement.size()); 49837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes callbackContext->replacementCharCount = replacement.size(); 49937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes 500cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UErrorCode errorCode = U_ZERO_ERROR; 50137871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes ucnv_setToUCallBack(cnv, CHARSET_DECODER_CALLBACK, callbackContext, NULL, NULL, &errorCode); 5025ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes maybeThrowIcuException(env, "ucnv_setToUCallBack", errorCode); 503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5057d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic jfloat NativeConverter_getAveCharsPerByte(JNIEnv* env, jclass, jlong handle) { 5067d52d787302b862019da41aa753646d88d43fd61Elliott Hughes return (1 / (jfloat) NativeConverter_getMaxBytesPerChar(env, NULL, handle)); 507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5097d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic jbyteArray NativeConverter_getSubstitutionBytes(JNIEnv* env, jclass, jlong address) { 510ac0ccbb85b4a96ba79b4e770f5b71687bf8f25e9Elliott Hughes UConverter* cnv = toUConverter(address); 511cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes if (cnv == NULL) { 512cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return NULL; 513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 514cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes UErrorCode status = U_ZERO_ERROR; 51537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes char replacementBytes[MAX_REPLACEMENT_LENGTH]; 51637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes int8_t len = sizeof(replacementBytes); 51737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes ucnv_getSubstChars(cnv, replacementBytes, &len, &status); 518cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes if (!U_SUCCESS(status)) { 519cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return env->NewByteArray(0); 520cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes } 521cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes jbyteArray result = env->NewByteArray(len); 522cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes if (result == NULL) { 523cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return NULL; 524cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes } 52537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes env->SetByteArrayRegion(result, 0, len, reinterpret_cast<jbyte*>(replacementBytes)); 526cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes return result; 527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5297d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic jboolean NativeConverter_contains(JNIEnv* env, jclass, jstring name1, jstring name2) { 5307d52d787302b862019da41aa753646d88d43fd61Elliott Hughes ScopedUtfChars name1Chars(env, name1); 5317d52d787302b862019da41aa753646d88d43fd61Elliott Hughes if (name1Chars.c_str() == NULL) { 5327d52d787302b862019da41aa753646d88d43fd61Elliott Hughes return JNI_FALSE; 533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 5347d52d787302b862019da41aa753646d88d43fd61Elliott Hughes ScopedUtfChars name2Chars(env, name2); 5357d52d787302b862019da41aa753646d88d43fd61Elliott Hughes if (name2Chars.c_str() == NULL) { 5367d52d787302b862019da41aa753646d88d43fd61Elliott Hughes return JNI_FALSE; 5377d52d787302b862019da41aa753646d88d43fd61Elliott Hughes } 5387d52d787302b862019da41aa753646d88d43fd61Elliott Hughes 5397d52d787302b862019da41aa753646d88d43fd61Elliott Hughes UErrorCode errorCode = U_ZERO_ERROR; 540a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::LocalUConverterPointer converter1(ucnv_open(name1Chars.c_str(), &errorCode)); 541a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeSet set1; 542ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes ucnv_getUnicodeSet(&*converter1, set1.toUSet(), UCNV_ROUNDTRIP_SET, &errorCode); 5437d52d787302b862019da41aa753646d88d43fd61Elliott Hughes 544a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::LocalUConverterPointer converter2(ucnv_open(name2Chars.c_str(), &errorCode)); 545a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeSet set2; 546ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes ucnv_getUnicodeSet(&*converter2, set2.toUSet(), UCNV_ROUNDTRIP_SET, &errorCode); 5477d52d787302b862019da41aa753646d88d43fd61Elliott Hughes 5487d52d787302b862019da41aa753646d88d43fd61Elliott Hughes return U_SUCCESS(errorCode) && set1.containsAll(set2); 549bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes} 550bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes 5517d52d787302b862019da41aa753646d88d43fd61Elliott Hughesstatic jobject NativeConverter_charsetForName(JNIEnv* env, jclass, jstring charsetName) { 552bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes ScopedUtfChars charsetNameChars(env, charsetName); 55305960876dff6a5b686821eed8f7ae7cef5af4f50Elliott Hughes if (charsetNameChars.c_str() == NULL) { 554bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return NULL; 555bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes } 556ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes 557bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes // Get ICU's canonical name for this charset. 5580808cae1a2616ba9c708c7cc4489723b4060178eElliott Hughes const char* icuCanonicalName = getICUCanonicalName(charsetNameChars.c_str()); 559bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (icuCanonicalName == NULL) { 560bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return NULL; 561bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes } 562ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes 563bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes // Get Java's canonical name for this charset. 564bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes jstring javaCanonicalName = getJavaCanonicalName(env, icuCanonicalName); 5656c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes if (env->ExceptionCheck()) { 566bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return NULL; 567bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes } 568bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes 569bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes // Check that this charset is supported. 570ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes { 571ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes // ICU doesn't offer any "isSupported", so we just open and immediately close. 572ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes UErrorCode error = U_ZERO_ERROR; 573a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::LocalUConverterPointer cnv(ucnv_open(icuCanonicalName, &error)); 574ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes if (!U_SUCCESS(error)) { 575ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes return NULL; 576ea1caf4ccc5c2255f384c0774aa9e055763a6a41Elliott Hughes } 577bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes } 578bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes 579bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes // Get the aliases for this charset. 580783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes std::vector<std::string> aliases; 581783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes if (!collectStandardNames(env, icuCanonicalName, "IANA", aliases)) { 582783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes return NULL; 583783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes } 584783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes if (!collectStandardNames(env, icuCanonicalName, "MIME", aliases)) { 585783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes return NULL; 586783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes } 587783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes if (!collectStandardNames(env, icuCanonicalName, "JAVA", aliases)) { 588783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes return NULL; 589783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes } 590783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes if (!collectStandardNames(env, icuCanonicalName, "WINDOWS", aliases)) { 591783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes return NULL; 592783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes } 593783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes jobjectArray javaAliases = toStringArray(env, aliases); 5946c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes if (env->ExceptionCheck()) { 595bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return NULL; 596bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes } 597bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes 598bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes // Construct the CharsetICU object. 5996c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes static jmethodID charsetConstructor = env->GetMethodID(JniConstants::charsetICUClass, "<init>", 600bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V"); 6016c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes if (env->ExceptionCheck()) { 602bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return NULL; 603bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes } 6048fbe7d8a9df5f464da59a2938acaf211845b89daYi Kong 6058fbe7d8a9df5f464da59a2938acaf211845b89daYi Kong jstring icuCanonicalNameStr = env->NewStringUTF(icuCanonicalName); 6068fbe7d8a9df5f464da59a2938acaf211845b89daYi Kong if (env->ExceptionCheck()) { 6078fbe7d8a9df5f464da59a2938acaf211845b89daYi Kong return NULL; 6088fbe7d8a9df5f464da59a2938acaf211845b89daYi Kong } 6098fbe7d8a9df5f464da59a2938acaf211845b89daYi Kong 610a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes return env->NewObject(JniConstants::charsetICUClass, charsetConstructor, 6118fbe7d8a9df5f464da59a2938acaf211845b89daYi Kong javaCanonicalName, icuCanonicalNameStr, javaAliases); 612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6141bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamathstatic void FreeNativeConverter(void *converter) { 6151bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath ucnv_close(reinterpret_cast<UConverter*>(converter)); 6161bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath} 6171bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath 6181bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamathstatic jlong NativeConverter_getNativeFinalizer(JNIEnv*, jclass) { 6191bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath return reinterpret_cast<jlong>(&FreeNativeConverter); 6201bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath} 6211bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath 6221bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath 6231bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamathstatic jlong NativeConverter_getNativeSize(JNIEnv*, jclass, jstring) { 6241bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath // TODO: Improve estimate. 6251bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath return 200; 6261bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath} 6271bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath 628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic JNINativeMethod gMethods[] = { 629e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, charsetForName, "(Ljava/lang/String;)Ljava/nio/charset/Charset;"), 630e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, closeConverter, "(J)V"), 631e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, contains, "(Ljava/lang/String;Ljava/lang/String;)Z"), 632e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, decode, "(J[BI[CI[IZ)I"), 633e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, encode, "(J[CI[BI[IZ)I"), 634e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, getAvailableCharsetNames, "()[Ljava/lang/String;"), 635e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, getAveBytesPerChar, "(J)F"), 636e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, getAveCharsPerByte, "(J)F"), 637e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, getMaxBytesPerChar, "(J)I"), 638e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, getMinBytesPerChar, "(J)I"), 639e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, getSubstitutionBytes, "(J)[B"), 640e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, openConverter, "(Ljava/lang/String;)J"), 641e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, resetByteToChar, "(J)V"), 642e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(NativeConverter, resetCharToByte, "(J)V"), 6435ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes NATIVE_METHOD(NativeConverter, setCallbackDecode, "(JIILjava/lang/String;)V"), 6445ec69b20ab9b3e2dcbe225d548168b09afbbbac2Elliott Hughes NATIVE_METHOD(NativeConverter, setCallbackEncode, "(JII[B)V"), 6451bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath NATIVE_METHOD(NativeConverter, getNativeFinalizer, "()J"), 6461bdc6bc1c72b033ed860360e69fc9f1f1121579bNarayan Kamath NATIVE_METHOD(NativeConverter, getNativeSize, "()J") 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}; 6487cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_libcore_icu_NativeConverter(JNIEnv* env) { 6497cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes jniRegisterNativeMethods(env, "libcore/icu/NativeConverter", gMethods, NELEM(gMethods)); 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 651