String (String str) { /* * Whether output escaping is enabled for the being processed * Element - default is <code>true</code> */ boolean escapeOutput = true; if (!escapeOutput) return str; StringBuilder buffer; int ch, pos; String entity; EscapeStrategy strategy = currentFormat.escapeStrategy; buffer = null; for (int i = 0; i < str.length(); i++) { ch = str.charAt(i); pos = i; switch (ch) { case '<': entity = "&lt;"; break; case '>': entity = "&gt;"; break; case '&': entity = "&amp;"; break; case '\r': entity = "&#xD;"; break; case '\n': entity = currentFormat.lineSeparator; break; default: if (strategy.shouldEscape((char)ch)) { //make sure what we are escaping is not the //beginning of a multi-byte character. if (Verifier.isHighSurrogate((char)ch)) { //this is a the high of a surrogate pair i++; if (i < str.length()) { char low = str.charAt(i); if (!Verifier.isLowSurrogate(low)) { throw new IllegalDataException("Could not decode surrogate pair 0x" + Integer.toHexString(ch) + " / 0x" + Integer.toHexString(low)); } ch = Verifier.decodeSurrogatePair((char)ch, low); } else { throw new IllegalDataException("Surrogate pair 0x" + Integer.toHexString(ch) + " truncated"); } } entity = "&#x" + Integer.toHexString(ch) + ";"; } else { entity = null; } break; } if (buffer == null) { if (entity != null) { // An entity occurred, so we'll have to use StringBuffer // (allocate room for it plus a few more entities). buffer = new StringBuilder(str.length() + 20); // Copy previous skipped characters and fall through // to pickup current character buffer.append(str, 0, pos); buffer.append(entity); } } else { if (entity == null) { buffer.append((char)ch); } else { buffer.append(entity); } } } // If there were any entities, return the escaped characters // that we put in the StringBuffer. Otherwise, just return // the unmodified input string. return (buffer == null) ? str : buffer.toString(); }