/** * Returns an immutable case-insensitive map from canonical names to {@code Charset} instances. * If multiple charsets have the same canonical name, it is unspecified which is returned in * the map. This method may be slow. If you know which charset you're looking for, use * {@link #forName}. */ public static SortedMap<String, Charset> availableCharsets() { // Start with a copy of the built-in charsets... TreeMap<String, Charset> charsets = new TreeMap<String, Charset>(String.CASE_INSENSITIVE_ORDER); for (String charsetName : NativeConverter.getAvailableCharsetNames()) { // RoboVM note: Added try-catch to ignore charsets with bad names (e.g. "x-UTF-16,version=1") try { Charset charset = NativeConverter.charsetForName(charsetName); charsets.put(charset.name(), charset); } catch (IllegalCharsetNameException e) { } } // Add all charsets provided by all charset providers... for (CharsetProvider charsetProvider : ServiceLoader.load(CharsetProvider.class)) { Iterator<Charset> it = charsetProvider.charsets(); while (it.hasNext()) { Charset cs = it.next(); // A CharsetProvider can't override a built-in Charset. if (!charsets.containsKey(cs.name())) { charsets.put(cs.name(), cs); } } } return Collections.unmodifiableSortedMap(charsets); }
public static CharsetEncoderICU newInstance(Charset cs, String icuCanonicalName) { // This complexity is necessary to ensure that even if the constructor, superclass // constructor, or call to updateCallback throw, we still free the native peer. long address = 0; try { address = NativeConverter.openConverter(icuCanonicalName); float averageBytesPerChar = NativeConverter.getAveBytesPerChar(address); float maxBytesPerChar = NativeConverter.getMaxBytesPerChar(address); byte[] replacement = makeReplacement(icuCanonicalName, address); CharsetEncoderICU result = new CharsetEncoderICU(cs, averageBytesPerChar, maxBytesPerChar, replacement, address); address = 0; // CharsetEncoderICU has taken ownership; its finalizer will do the free. return result; } finally { if (address != 0) { NativeConverter.closeConverter(address); } } }
public boolean contains(Charset cs) { if (cs == null) { return false; } else if (this.equals(cs)) { return true; } return NativeConverter.contains(this.name(), cs.name()); } }
public static CharsetDecoderICU newInstance(Charset cs, String icuCanonicalName) { // This complexity is necessary to ensure that even if the constructor, superclass // constructor, or call to updateCallback throw, we still free the native peer. long address = 0; try { address = NativeConverter.openConverter(icuCanonicalName); float averageCharsPerByte = NativeConverter.getAveCharsPerByte(address); CharsetDecoderICU result = new CharsetDecoderICU(cs, averageCharsPerByte, address); address = 0; // CharsetDecoderICU has taken ownership; its finalizer will do the free. result.updateCallback(); return result; } finally { if (address != 0) { NativeConverter.closeConverter(address); } } }
@Override protected void finalize() throws Throwable { try { NativeConverter.closeConverter(converterHandle); converterHandle=0; } finally { super.finalize(); } }
@Override protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { if (!in.hasRemaining()) { return CoderResult.UNDERFLOW; } data[INPUT_OFFSET] = getArray(in); data[OUTPUT_OFFSET]= getArray(out); data[INVALID_CHARS] = 0; // Make sure we don't see earlier errors. try { int error = NativeConverter.encode(converterHandle, input, inEnd, output, outEnd, data, false); if (ICU.U_FAILURE(error)) { if (error == ICU.U_BUFFER_OVERFLOW_ERROR) { return CoderResult.OVERFLOW; } else if (error == ICU.U_INVALID_CHAR_FOUND) { return CoderResult.unmappableForLength(data[INVALID_CHARS]); } else if (error == ICU.U_ILLEGAL_CHAR_FOUND) { return CoderResult.malformedForLength(data[INVALID_CHARS]); } else { throw new AssertionError(error); } } // Decoding succeeded: give us more data. return CoderResult.UNDERFLOW; } finally { setPosition(in); setPosition(out); } }
@Override protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) { if (!in.hasRemaining()) { return CoderResult.UNDERFLOW; } data[INPUT_OFFSET] = getArray(in); data[OUTPUT_OFFSET]= getArray(out); try { int error = NativeConverter.decode(converterHandle, input, inEnd, output, outEnd, data, false); if (ICU.U_FAILURE(error)) { if (error == ICU.U_BUFFER_OVERFLOW_ERROR) { return CoderResult.OVERFLOW; } else if (error == ICU.U_INVALID_CHAR_FOUND) { return CoderResult.unmappableForLength(data[INVALID_BYTES]); } else if (error == ICU.U_ILLEGAL_CHAR_FOUND) { return CoderResult.malformedForLength(data[INVALID_BYTES]); } else { throw new AssertionError(error); } } // Decoding succeeded: give us more data. return CoderResult.UNDERFLOW; } finally { setPosition(in); setPosition(out); } }
private static byte[] makeReplacement(String icuCanonicalName, long address) { // We have our own map of RI-compatible default replacements (where ICU disagrees)... byte[] replacement = DEFAULT_REPLACEMENTS.get(icuCanonicalName); if (replacement != null) { return replacement.clone(); } // ...but fall back to asking ICU. return NativeConverter.getSubstitutionBytes(address); }
cs = NativeConverter.charsetForName(charsetName); if (cs != null) { return cacheCharset(charsetName, cs);
public static CharsetDecoderICU newInstance(Charset cs, String icuCanonicalName) { // This complexity is necessary to ensure that even if the constructor, superclass // constructor, or call to updateCallback throw, we still free the native peer. long address = 0; try { address = NativeConverter.openConverter(icuCanonicalName); float averageCharsPerByte = NativeConverter.getAveCharsPerByte(address); CharsetDecoderICU result = new CharsetDecoderICU(cs, averageCharsPerByte, address); address = 0; // CharsetDecoderICU has taken ownership; its finalizer will do the free. result.updateCallback(); return result; } finally { if (address != 0) { NativeConverter.closeConverter(address); } } }
@Override protected void finalize() throws Throwable { try { NativeConverter.closeConverter(converterHandle); converterHandle = 0; } finally { super.finalize(); } }
@Override protected CoderResult implFlush(ByteBuffer out) { try { // ICU needs to see an empty input. input = EmptyArray.CHAR; inEnd = 0; data[INPUT_OFFSET] = 0; data[OUTPUT_OFFSET] = getArray(out); data[INVALID_CHARS] = 0; // Make sure we don't see earlier errors. int error = NativeConverter.encode(converterHandle, input, inEnd, output, outEnd, data, true); if (ICU.U_FAILURE(error)) { if (error == ICU.U_BUFFER_OVERFLOW_ERROR) { return CoderResult.OVERFLOW; } else if (error == ICU.U_TRUNCATED_CHAR_FOUND) { if (data[INPUT_OFFSET] > 0) { return CoderResult.malformedForLength(data[INPUT_OFFSET]); } } } return CoderResult.UNDERFLOW; } finally { setPosition(out); implReset(); } }
@Override protected final CoderResult implFlush(CharBuffer out) { try { // ICU needs to see an empty input. input = EmptyArray.BYTE; inEnd = 0; data[INPUT_OFFSET] = 0; data[OUTPUT_OFFSET] = getArray(out); data[INVALID_BYTES] = 0; // Make sure we don't see earlier errors. int error = NativeConverter.decode(converterHandle, input, inEnd, output, outEnd, data, true); if (ICU.U_FAILURE(error)) { if (error == ICU.U_BUFFER_OVERFLOW_ERROR) { return CoderResult.OVERFLOW; } else if (error == ICU.U_TRUNCATED_CHAR_FOUND) { if (data[INPUT_OFFSET] > 0) { return CoderResult.malformedForLength(data[INPUT_OFFSET]); } } } return CoderResult.UNDERFLOW; } finally { setPosition(out); implReset(); } }
private static byte[] makeReplacement(String icuCanonicalName, long address) { // We have our own map of RI-compatible default replacements (where ICU disagrees)... byte[] replacement = DEFAULT_REPLACEMENTS.get(icuCanonicalName); if (replacement != null) { return replacement.clone(); } // ...but fall back to asking ICU. return NativeConverter.getSubstitutionBytes(address); }
cs = NativeConverter.charsetForName(charsetName); if (cs != null) { return cacheCharset(charsetName, cs);
public static CharsetEncoderICU newInstance(Charset cs, String icuCanonicalName) { // This complexity is necessary to ensure that even if the constructor, superclass // constructor, or call to updateCallback throw, we still free the native peer. long address = 0; try { address = NativeConverter.openConverter(icuCanonicalName); float averageBytesPerChar = NativeConverter.getAveBytesPerChar(address); float maxBytesPerChar = NativeConverter.getMaxBytesPerChar(address); byte[] replacement = makeReplacement(icuCanonicalName, address); CharsetEncoderICU result = new CharsetEncoderICU(cs, averageBytesPerChar, maxBytesPerChar, replacement, address); address = 0; // CharsetEncoderICU has taken ownership; its finalizer will do the free. return result; } finally { if (address != 0) { NativeConverter.closeConverter(address); } } }
public static CharsetDecoderICU newInstance(Charset cs, String icuCanonicalName) { // This complexity is necessary to ensure that even if the constructor, superclass // constructor, or call to updateCallback throw, we still free the native peer. long address = 0; try { address = NativeConverter.openConverter(icuCanonicalName); float averageCharsPerByte = NativeConverter.getAveCharsPerByte(address); CharsetDecoderICU result = new CharsetDecoderICU(cs, averageCharsPerByte, address); address = 0; // CharsetDecoderICU has taken ownership; its finalizer will do the free. result.updateCallback(); return result; } finally { if (address != 0) { NativeConverter.closeConverter(address); } } }
/** * Returns an immutable case-insensitive map from canonical names to {@code Charset} instances. * If multiple charsets have the same canonical name, it is unspecified which is returned in * the map. This method may be slow. If you know which charset you're looking for, use * {@link #forName}. */ public static SortedMap<String, Charset> availableCharsets() { // Start with a copy of the built-in charsets... TreeMap<String, Charset> charsets = new TreeMap<String, Charset>(String.CASE_INSENSITIVE_ORDER); for (String charsetName : NativeConverter.getAvailableCharsetNames()) { // BugVM note: Added try-catch to ignore charsets with bad names (e.g. "x-UTF-16,version=1") try { Charset charset = NativeConverter.charsetForName(charsetName); charsets.put(charset.name(), charset); } catch (IllegalCharsetNameException e) { } } // Add all charsets provided by all charset providers... for (CharsetProvider charsetProvider : ServiceLoader.load(CharsetProvider.class)) { Iterator<Charset> it = charsetProvider.charsets(); while (it.hasNext()) { Charset cs = it.next(); // A CharsetProvider can't override a built-in Charset. if (!charsets.containsKey(cs.name())) { charsets.put(cs.name(), cs); } } } return Collections.unmodifiableSortedMap(charsets); }
@Override protected void finalize() throws Throwable { try { NativeConverter.closeConverter(converterHandle); converterHandle=0; } finally { super.finalize(); } }
@Override protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { if (!in.hasRemaining()) { return CoderResult.UNDERFLOW; } data[INPUT_OFFSET] = getArray(in); data[OUTPUT_OFFSET]= getArray(out); data[INVALID_CHARS] = 0; // Make sure we don't see earlier errors. try { int error = NativeConverter.encode(converterHandle, input, inEnd, output, outEnd, data, false); if (ICU.U_FAILURE(error)) { if (error == ICU.U_BUFFER_OVERFLOW_ERROR) { return CoderResult.OVERFLOW; } else if (error == ICU.U_INVALID_CHAR_FOUND) { return CoderResult.unmappableForLength(data[INVALID_CHARS]); } else if (error == ICU.U_ILLEGAL_CHAR_FOUND) { return CoderResult.malformedForLength(data[INVALID_CHARS]); } else { throw new AssertionError(error); } } // Decoding succeeded: give us more data. return CoderResult.UNDERFLOW; } finally { setPosition(in); setPosition(out); } }