String (EscapeStrategy strategy, String value) { final int len = value.length(); int idx = 0; checkloop: while (idx < len) { final char ch = value.charAt(idx); if (ch == '<' || ch == '>' || ch == '&' || ch == '\r' || ch == '\n' || ch == '"' || ch == '\t' || strategy.shouldEscape(ch)) { break checkloop; } idx++; } if (idx == len) { return value; } char highsurrogate = 0; final StringBuilder sb = new StringBuilder(len + 5); sb.append(value, 0, idx); while (idx < len) { final char ch = value.charAt(idx++); if (highsurrogate > 0) { if (!Verifier.isLowSurrogate(ch)) { throw new IllegalDataException( "Could not decode surrogate pair 0x" + Integer.toHexString(highsurrogate) + " / 0x" + Integer.toHexString(ch)); } int chp = Verifier.decodeSurrogatePair(highsurrogate, ch); sb.append("&#x"); sb.append(Integer.toHexString(chp)); sb.append(';'); highsurrogate = 0; continue; } switch (ch) { case '<': sb.append("&lt;"); break; case '>': sb.append("&gt;"); break; case '&': sb.append("&amp;"); break; case '\r': sb.append("&#xD;"); break; case '"': sb.append("&quot;"); break; case '\t': sb.append("&#x9;"); break; case '\n': sb.append("&#xA;"); break; default: if (strategy.shouldEscape(ch)) { // make sure what we are escaping is not the // beginning of a multi-byte character. if (Verifier.isHighSurrogate(ch)) { // this is a the high of a surrogate pair highsurrogate = ch; } else { sb.append("&#x"); sb.append(Integer.toHexString(ch)); sb.append(';'); } } else { sb.append(ch); } break; } } if (highsurrogate > 0) { throw new IllegalDataException("Surrogate pair 0x" + Integer.toHexString(highsurrogate) + "truncated"); } return sb.toString(); }