CharsetICU.java revision c60bc1815dca549f3fb4e572f6aac749d7fa9fc6
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project******************************************************************************* 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project* Copyright (C) 1996-2005, 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******************************************************************************* 8ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes*/ 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage com.ibm.icu4jni.charset; 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.Charset; 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.CharsetDecoder; 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.CharsetEncoder; 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.HashMap; 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Map; 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18ebe438a0734f24ded1772778e5e712c820981234Elliott Hughespublic final class CharsetICU extends Charset { 19c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes private static final Map<String, byte[]> DEFAULT_REPLACEMENTS = new HashMap<String, byte[]>(); 20c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes static { 21c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // ICU has different default replacements to the RI in these cases. There are probably 22c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // more cases too, but this covers all the charsets that Java guarantees will be available. 23c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // These use U+FFFD REPLACEMENT CHARACTER... 24c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes DEFAULT_REPLACEMENTS.put("UTF-16", new byte[] { (byte) 0xff, (byte) 0xfd }); 25c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes DEFAULT_REPLACEMENTS.put("UTF-32", new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xfd }); 26c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // These use '?'. It's odd that UTF-8 doesn't use U+FFFD, given that (unlike ISO-8859-1 27c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // and US-ASCII) it can represent it, but this is what the RI does... 28c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes byte[] questionMark = new byte[] { (byte) '?' }; 29c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes DEFAULT_REPLACEMENTS.put("UTF-8", questionMark); 30c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes DEFAULT_REPLACEMENTS.put("ISO-8859-1", questionMark); 31c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes DEFAULT_REPLACEMENTS.put("US-ASCII", questionMark); 32c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes } 33c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes 34bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes private final String icuCanonicalName; 35c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected CharsetICU(String canonicalName, String icuCanonName, String[] aliases) { 37bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes super(canonicalName, aliases); 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project icuCanonicalName = icuCanonName; 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 40c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes 41bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes public CharsetDecoder newDecoder() { 42c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes return new CharsetDecoderICU(this, NativeConverter.openConverter(icuCanonicalName)); 43bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes } 44ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes 45ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes public CharsetEncoder newEncoder() { 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long converterHandle = NativeConverter.openConverter(icuCanonicalName); 47c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // We have our own map of RI-compatible default replacements... 48c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes byte[] replacement = DEFAULT_REPLACEMENTS.get(icuCanonicalName); 49c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes if (replacement == null) { 50c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // ...but fall back to asking ICU. 51c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // TODO: should we just try to use U+FFFD and fall back to '?' if U+FFFD can't be encoded? 52c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes replacement = NativeConverter.getSubstitutionBytes(converterHandle); 53c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes } else { 54c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes replacement = replacement.clone(); 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 56c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes return new CharsetEncoderICU(this, converterHandle, replacement); 57ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes } 58ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes 59c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes public boolean contains(Charset cs) { 60c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes if (cs == null) { 61c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes return false; 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (this.equals(cs)) { 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 65ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long converterHandle1 = 0; 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long converterHandle2 = 0; 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project converterHandle1 = NativeConverter.openConverter(this.name()); 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (converterHandle1 > 0) { 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project converterHandle2 = NativeConverter.openConverter(cs.name()); 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (converterHandle2 > 0) { 74c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes return NativeConverter.contains(converterHandle1, converterHandle2); 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (0 != converterHandle1) { 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project NativeConverter.closeConverter(converterHandle1); 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (0 != converterHandle2) { 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project NativeConverter.closeConverter(converterHandle2); 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 88