12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others. 22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert******************************************************************************* 57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Copyright (C) 2006-2014, International Business Machines Corporation and 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* others. All Rights Reserved. 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert******************************************************************************* 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/ 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.charset; 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.ByteBuffer; 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.CharBuffer; 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.IntBuffer; 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.charset.CoderResult; 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h2> Callback API for CharsetICU API </h2> 192d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert * 202d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert * CharsetCallback class defines some error behaviour functions called 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * by CharsetDecoderICU and CharsetEncoderICU. The class also provides 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the facility by which clients can write their own callbacks. 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * These functions, although public, should NEVER be called directly. 252d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert * They should be used as parameters to the onUmappableCharacter() and 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * onMalformedInput() methods, to set the behaviour of a converter 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * when it encounters UNMAPPED/INVALID sequences. 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Currently the only way to set callbacks is by using CodingErrorAction. 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * In the future we will provide set methods on CharsetEncoder and CharsetDecoder 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * that will accept CharsetCallback fields. 317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class CharsetCallback { 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * FROM_U, TO_U context options for sub callback 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String SUB_STOP_ON_ILLEGAL = "i"; 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// /* 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// * FROM_U, TO_U context options for skip callback 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// */ 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// private static final String SKIP_STOP_ON_ILLEGAL = "i"; 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// /* 472d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// * FROM_U_CALLBACK_ESCAPE context option to escape the code unit according to ICU (%UXXXX) 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// */ 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// private static final String ESCAPE_ICU = null; 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * FROM_U_CALLBACK_ESCAPE context option to escape the code unit according to JAVA (\\uXXXX) 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String ESCAPE_JAVA = "J"; 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * FROM_U_CALLBACK_ESCAPE context option to escape the code unit according to C (\\uXXXX \\UXXXXXXXX) 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TO_U_CALLBACK_ESCAPE option to escape the character value accoding to C (\\xXXXX) 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String ESCAPE_C = "C"; 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * FROM_U_CALLBACK_ESCAPE context option to escape the code unit according to XML Decimal escape \htmlonly(&#DDDD;)\endhtmlonly 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TO_U_CALLBACK_ESCAPE context option to escape the character value accoding to XML Decimal escape \htmlonly(&#DDDD;)\endhtmlonly 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String ESCAPE_XML_DEC = "D"; 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * FROM_U_CALLBACK_ESCAPE context option to escape the code unit according to XML Hex escape \htmlonly(&#xXXXX;)\endhtmlonly 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TO_U_CALLBACK_ESCAPE context option to escape the character value according to XML Hex escape \htmlonly(&#xXXXX;)\endhtmlonly 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String ESCAPE_XML_HEX = "X"; 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * FROM_U_CALLBACK_ESCAPE context option to escape the code unit according to Unicode (U+XXXXX) 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String ESCAPE_UNICODE = "U"; 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * FROM_U_CALLBACK_ESCAPE context option to escape the code unit according to Unicode (U+XXXXX) 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String ESCAPE_CSS2 = "S"; 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * IS_DEFAULT_IGNORABLE_CODE_POINT 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is to check if a code point has the default ignorable unicode property. 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * As such, this list needs to be updated if the ignorable code point list ever 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * changes. 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * To avoid dependency on other code, this list is hard coded here. 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * When an ignorable code point is found and is unmappable, the default callbacks 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * will ignore them. 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For a list of the default ignorable code points, use this link: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[%3ADI%3A]&g= 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This list should be sync with the one in ucnv_err.c 952d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert * 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static boolean IS_DEFAULT_IGNORABLE_CODE_POINT(int c) { 982d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert return ((c == 0x00AD) || 992d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (c == 0x034F) || 1002d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (c == 0x061C) || 1012d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (c == 0x115F) || 1022d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (c == 0x1160) || 1032d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x17B4 <= c && c <= 0x17B5) || 1042d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x180B <= c && c <= 0x180E) || 1052d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x200B <= c && c <= 0x200F) || 1062d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x202A <= c && c <= 0x202E) || 1072d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (c == 0x2060) || 1082d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x2066 <= c && c <= 0x2069) || 1092d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x2061 <= c && c <= 0x2064) || 1102d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x206A <= c && c <= 0x206F) || 1112d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (c == 0x3164) || 1122d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x0FE00 <= c && c <= 0x0FE0F) || 1132d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (c == 0x0FEFF) || 1142d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (c == 0x0FFA0) || 1152d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x01BCA0 <= c && c <= 0x01BCA3) || 1162d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x01D173 <= c && c <= 0x01D17A) || 1172d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (c == 0x0E0001) || 1182d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x0E0020 <= c && c <= 0x0E007F) || 1192d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x0E0100 <= c && c <= 0x0E01EF) || 1202d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (c == 0x2065) || 1212d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x0FFF0 <= c && c <= 0x0FFF8) || 1222d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (c == 0x0E0000) || 1232d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x0E0002 <= c && c <= 0x0E001F) || 1242d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert (0x0E0080 <= c && c <= 0x0E00FF) || 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (0x0E01F0 <= c && c <= 0x0E0FFF) 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ); 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Decoder Callback interface 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public interface Decoder { 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This function is called when the bytes in the source cannot be handled, 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and this function is meant to handle or fix the error if possible. 1362d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert * 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return Result of decoding action. This returned object is set to an error 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if this function could not handle the conversion. 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1412d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert public CoderResult call(CharsetDecoderICU decoder, Object context, 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ByteBuffer source, CharBuffer target, IntBuffer offsets, 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] buffer, int length, CoderResult cr); 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Encoder Callback interface 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public interface Encoder { 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This function is called when the Unicode characters in the source cannot be handled, 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and this function is meant to handle or fix the error if possible. 1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return Result of decoding action. This returned object is set to an error 1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if this function could not handle the conversion. 1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1572d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert public CoderResult call(CharsetEncoderICU encoder, Object context, 1582d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert CharBuffer source, ByteBuffer target, IntBuffer offsets, 1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] buffer, int length, int cp, CoderResult cr); 1602d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert } 1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Skip callback 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final Encoder FROM_U_CALLBACK_SKIP = new Encoder() { 1662d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 1672d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert public CoderResult call(CharsetEncoderICU encoder, Object context, 1682d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert CharBuffer source, ByteBuffer target, IntBuffer offsets, 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] buffer, int length, int cp, CoderResult cr){ 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(context==null){ 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return CoderResult.UNDERFLOW; 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }else if(((String)context).equals(SUB_STOP_ON_ILLEGAL)){ 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(!cr.isUnmappable()){ 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cr; 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }else{ 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return CoderResult.UNDERFLOW; 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cr; 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Skip callback 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final Decoder TO_U_CALLBACK_SKIP = new Decoder() { 1872d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 1882d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert public CoderResult call(CharsetDecoderICU decoder, Object context, 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ByteBuffer source, CharBuffer target, IntBuffer offsets, 1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] buffer, int length, CoderResult cr){ 1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(context==null){ 1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return CoderResult.UNDERFLOW; 1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }else if(((String)context).equals(SUB_STOP_ON_ILLEGAL)){ 1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(!cr.isUnmappable()){ 1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cr; 1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }else{ 1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return CoderResult.UNDERFLOW; 1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cr; 2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Write substitute callback 2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2072d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert public static final Encoder FROM_U_CALLBACK_SUBSTITUTE = new Encoder(){ 2082d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 2092d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert public CoderResult call(CharsetEncoderICU encoder, Object context, 2102d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert CharBuffer source, ByteBuffer target, IntBuffer offsets, 2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] buffer, int length, int cp, CoderResult cr){ 2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (cr.isUnmappable() && IS_DEFAULT_IGNORABLE_CODE_POINT(cp)) { 2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return CoderResult.UNDERFLOW; 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }else if(context==null){ 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return encoder.cbFromUWriteSub(encoder, source, target, offsets); 2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }else if(((String)context).equals(SUB_STOP_ON_ILLEGAL)){ 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(!cr.isUnmappable()){ 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cr; 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }else{ 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return encoder.cbFromUWriteSub(encoder, source, target, offsets); 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cr; 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char[] kSubstituteChar1 = new char[]{0x1A}; 2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char[] kSubstituteChar = new char[] {0xFFFD}; 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Write substitute callback 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final Decoder TO_U_CALLBACK_SUBSTITUTE = new Decoder() { 2332d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 2342d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert public CoderResult call(CharsetDecoderICU decoder, Object context, 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ByteBuffer source, CharBuffer target, IntBuffer offsets, 2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] buffer, int length, CoderResult cr){ 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CharsetICU cs = (CharsetICU) decoder.charset(); 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Use the specified replacement character if it is different than the default one. */ 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean useReplacement = true; 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char [] replacementChar = decoder.replacement().toCharArray(); 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (replacementChar.length == 1 && (replacementChar[0] == kSubstituteChar1[0] || replacementChar[0] == kSubstituteChar[0])) { 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useReplacement = false; 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2452d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* could optimize this case, just one uchar */ 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(decoder.invalidCharLength == 1 && cs.subChar1 != 0) { 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return CharsetDecoderICU.toUWriteUChars(decoder, useReplacement ? replacementChar : kSubstituteChar1, 0, useReplacement ? replacementChar.length : 1, target, offsets, source.position()); 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return CharsetDecoderICU.toUWriteUChars(decoder, useReplacement ? replacementChar : kSubstituteChar, 0, useReplacement ? replacementChar.length : 1, target, offsets, source.position()); 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Stop callback 2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final Encoder FROM_U_CALLBACK_STOP = new Encoder() { 2592d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 2602d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert public CoderResult call(CharsetEncoderICU encoder, Object context, 2612d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert CharBuffer source, ByteBuffer target, IntBuffer offsets, 2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] buffer, int length, int cp, CoderResult cr){ 2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (cr.isUnmappable() && IS_DEFAULT_IGNORABLE_CODE_POINT(cp)) { 2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return CoderResult.UNDERFLOW; 2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cr; 2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Stop callback 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final Decoder TO_U_CALLBACK_STOP = new Decoder() { 2742d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 2752d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert public CoderResult call(CharsetDecoderICU decoder, Object context, 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ByteBuffer source, CharBuffer target, IntBuffer offsets, 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] buffer, int length, CoderResult cr){ 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cr; 2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2802d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert }; 2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int VALUE_STRING_LENGTH = 32; 2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_PERCENT_SIGN_CODEPOINT = 0x0025; 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_U_CODEPOINT = 0x0055; 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_X_CODEPOINT = 0x0058; 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_RS_CODEPOINT = 0x005C; 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_U_LOW_CODEPOINT = 0x0075; 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_X_LOW_CODEPOINT = 0x0078; 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_AMP_CODEPOINT = 0x0026; 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_HASH_CODEPOINT = 0x0023; 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_SEMICOLON_CODEPOINT = 0x003B; 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_PLUS_CODEPOINT = 0x002B; 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_LEFT_CURLY_CODEPOINT = 0x007B; 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_RIGHT_CURLY_CODEPOINT = 0x007D; 2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char UNICODE_SPACE_CODEPOINT = 0x0020; 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Write escape callback 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final Encoder FROM_U_CALLBACK_ESCAPE = new Encoder() { 3002d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 3012d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert public CoderResult call(CharsetEncoderICU encoder, Object context, 3022d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert CharBuffer source, ByteBuffer target, IntBuffer offsets, 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] buffer, int length, int cp, CoderResult cr){ 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] valueString = new char[VALUE_STRING_LENGTH]; 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int valueStringLength = 0; 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i = 0; 3072d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (cr.isUnmappable() && IS_DEFAULT_IGNORABLE_CODE_POINT(cp)) { 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return CoderResult.UNDERFLOW; 3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3112d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert 3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (context == null || !(context instanceof String)) { 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i < length) { 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_PERCENT_SIGN_CODEPOINT; /* adding % */ 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_U_CODEPOINT; /* adding U */ 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(valueString, valueStringLength, buffer[i++], 16, 4); 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (((String)context).equals(ESCAPE_JAVA)) { 3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i < length) { 3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_RS_CODEPOINT; /* adding \ */ 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_U_LOW_CODEPOINT; /* adding u */ 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(valueString, valueStringLength, buffer[i++], 16, 4); 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (((String)context).equals(ESCAPE_C)) { 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_RS_CODEPOINT; /* adding \ */ 3272d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert 3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (length == 2) { 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_U_CODEPOINT; /* adding U */ 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength = itou(valueString, valueStringLength, cp, 16, 8); 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_U_LOW_CODEPOINT; /* adding u */ 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(valueString, valueStringLength, buffer[0], 16, 4); 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (((String)context).equals(ESCAPE_XML_DEC)) { 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_AMP_CODEPOINT; /* adding & */ 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_HASH_CODEPOINT; /* adding # */ 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (length == 2) { 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(valueString, valueStringLength, cp, 10, 0); 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(valueString, valueStringLength, buffer[0], 10, 0); 3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_SEMICOLON_CODEPOINT; /* adding ; */ 3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (((String)context).equals(ESCAPE_XML_HEX)) { 3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_AMP_CODEPOINT; /* adding & */ 3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_HASH_CODEPOINT; /* adding # */ 3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_X_LOW_CODEPOINT; /* adding x */ 3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (length == 2) { 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(valueString, valueStringLength, cp, 16, 0); 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(valueString, valueStringLength, buffer[0], 16, 0); 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_SEMICOLON_CODEPOINT; /* adding ; */ 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (((String)context).equals(ESCAPE_UNICODE)) { 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_LEFT_CURLY_CODEPOINT; /* adding { */ 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_U_CODEPOINT; /* adding U */ 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_PLUS_CODEPOINT; /* adding + */ 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (length == 2) { 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(valueString, valueStringLength,cp, 16, 4); 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(valueString, valueStringLength, buffer[0], 16, 4); 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_RIGHT_CURLY_CODEPOINT; /* adding } */ 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (((String)context).equals(ESCAPE_CSS2)) { 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_RS_CODEPOINT; /* adding \ */ 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(valueString, valueStringLength, cp, 16, 0); 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* Always add space character, because the next character might be whitespace, 3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert which would erroneously be considered the termination of the escape sequence. */ 3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_SPACE_CODEPOINT; 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i < length) { 3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_PERCENT_SIGN_CODEPOINT; /* adding % */ 3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueString[valueStringLength++] = UNICODE_U_CODEPOINT; /* adding U */ 3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(valueString, valueStringLength, buffer[i++], 16, 4); 3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return encoder.cbFromUWriteUChars(encoder, CharBuffer.wrap(valueString, 0, valueStringLength), target, offsets); 3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Write escape callback 3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final Decoder TO_U_CALLBACK_ESCAPE = new Decoder() { 3862d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 3872d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert public CoderResult call(CharsetDecoderICU decoder, Object context, 3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ByteBuffer source, CharBuffer target, IntBuffer offsets, 3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] buffer, int length, CoderResult cr){ 3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] uniValueString = new char[VALUE_STRING_LENGTH]; 3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int valueStringLength = 0; 3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i = 0; 3932d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert 3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (context == null || !(context instanceof String)) { 3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i < length) { 3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_PERCENT_SIGN_CODEPOINT; /* adding % */ 3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_X_CODEPOINT; /* adding U */ 3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(uniValueString, valueStringLength, buffer[i++] & UConverterConstants.UNSIGNED_BYTE_MASK, 16, 2); 3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (((String)context).equals(ESCAPE_XML_DEC)) { 4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i < length) { 4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_AMP_CODEPOINT; /* adding & */ 4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_HASH_CODEPOINT; /* adding # */ 4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(uniValueString, valueStringLength, buffer[i++] & UConverterConstants.UNSIGNED_BYTE_MASK, 10, 0); 4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_SEMICOLON_CODEPOINT; /* adding ; */ 4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (((String)context).equals(ESCAPE_XML_HEX)) { 4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i < length) { 4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_AMP_CODEPOINT; /* adding & */ 4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_HASH_CODEPOINT; /* adding # */ 4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_X_LOW_CODEPOINT; /* adding x */ 4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(uniValueString, valueStringLength, buffer[i++] & UConverterConstants.UNSIGNED_BYTE_MASK, 16, 0); 4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_SEMICOLON_CODEPOINT; /* adding ; */ 4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (((String)context).equals(ESCAPE_C)) { 4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i < length) { 4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_RS_CODEPOINT; /* adding \ */ 4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_X_LOW_CODEPOINT; /* adding x */ 4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += itou(uniValueString, valueStringLength, buffer[i++] & UConverterConstants.UNSIGNED_BYTE_MASK, 16, 2); 4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i < length) { 4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_PERCENT_SIGN_CODEPOINT; /* adding % */ 4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uniValueString[valueStringLength++] = UNICODE_X_CODEPOINT; /* adding X */ 4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert itou(uniValueString, valueStringLength, buffer[i++] & UConverterConstants.UNSIGNED_BYTE_MASK, 16, 2); 4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert valueStringLength += 2; 4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4312d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert 4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cr = CharsetDecoderICU.toUWriteUChars(decoder, uniValueString, 0, valueStringLength, target, offsets, 0); 4332d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert 4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return cr; 4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4362d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert }; 4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*** 4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Java port of uprv_itou() in ICU4C used by TO_U_CALLBACK_ESCAPE and FROM_U_CALLBACK_ESCAPE. 4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Fills in a char string with the radix-based representation of a number padded with zeroes 4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to minwidth. 4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int itou(char[] buffer, int sourceIndex, int i, int radix, int minwidth) { 4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int length = 0; 4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int digit; 4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int j; 4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char temp; 4472d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert 4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert do { 4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digit = i % radix; 4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer[sourceIndex + length++] = (char)(digit <= 9 ? (0x0030+digit) : (0x0030+digit+7)); 4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = i/radix; 4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } while (i != 0 && (sourceIndex + length) < buffer.length); 4532d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert 4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (length < minwidth) { 4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer[sourceIndex + length++] = (char)0x0030; /* zero padding */ 4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* reverses the string */ 4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (j = 0; j < (length / 2); j++) { 4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert temp = buffer[(sourceIndex + length - 1) - j]; 4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer[(sourceIndex + length-1) -j] = buffer[sourceIndex + j]; 4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer[sourceIndex + j] = temp; 4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4632d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert 4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return length; 4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * No need to create an instance 4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private CharsetCallback() { 4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 473