< prev index next >

src/java.base/share/classes/java/lang/String.java

Print this page
rev 51726 : 8202442: String::unescape
Reviewed-by: smarks, rriggs, sherman

*** 2970,2979 **** --- 2970,3167 ---- .orElse(0); return indent(n - outdent, true); } /** + * Translates all Unicode escapes and escape sequences in this string into + * characters represented by those escapes specified in sections 3.3 and + * 3.10.6 of the <cite>The Java&trade; Language Specification</cite>. + * <p> + * Each unicode escape in the form \unnnn is translated to a + * 16-bit 'char' value. + * <p> + * Backslash escape sequences are translated as follows; + * <table class="plain"> + * <caption style="display:none">Escape sequences</caption> + * <thead> + * <tr> + * <th scope="col">Escape</th> + * <th scope="col">Name</th> + * <th scope="col">Unicode</th> + * </tr> + * </thead> + * <tr> + * <td>{@code \b}</td> + * <td>backspace</td> + * <td>U+0008</td> + * </tr> + * <tr> + * <td>{@code \t}</td> + * <td>horizontal tab</td> + * <td>U+0009</td> + * </tr> + * <tr> + * <td>{@code \n}</td> + * <td>line feed</td> + * <td>U+000A</td> + * </tr> + * <tr> + * <td>{@code \f}</td> + * <td>form feed</td> + * <td>U+000C</td> + * </tr> + * <tr> + * <td>{@code \r}</td> + * <td>carriage return</td> + * <td>U+000D</td> + * </tr> + * <tr> + * <td>{@code \"}</td> + * <td>double quote</td> + * <td>U+0022</td> + * </tr> + * <tr> + * <td>{@code \'}</td> + * <td>single quote</td> + * <td>U+0027</td> + * </tr> + * <tr> + * <td>{@code \\}</td> + * <td>backslash</td> + * <td>U+005C</td> + * </tr> + * </table> + * <p> + * Octal escapes {@code \0 - \377} are translated to their code + * point equivalents. + * + * @return String with all escapes translated. + * + * @throws IllegalArgumentException when the escape sequence does + * not conform to JLS 3.3 or 3.10.6. + * + * @jls 3.3 Unicode escapes + * @jls 3.10.6 Escape sequences + * + * @since 12 + * + * @deprecated Preview feature associated with Raw String Literals. + */ + @Deprecated(forRemoval=true, since="12") + public String unescape() { + UnicodeReader reader = new UnicodeReader(); + int length = reader.length(); + char[] chars = new char[length]; + int to = 0; + while (reader.hasNext()) { + char ch = reader.next(); + if (ch == '\\') { + if (!reader.hasNext()) { + reader.error("truncated escape sequence"); + } + ch = reader.next(); + switch (ch) { + case 'b': + ch = '\b'; + break; + case 'f': + ch = '\f'; + break; + case 'n': + ch = '\n'; + break; + case 'r': + ch = '\r'; + break; + case 't': + ch = '\t'; + break; + case '\\': + ch = '\\'; + break; + case '\'': + ch = '\''; + break; + case '\"': + ch = '\"'; + break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + int code = ch - '0'; + for (int i = 0; i < 2 && reader.hasNext(); i++) { + int digit = Character.digit(reader.next(), 8); + if (digit < 0) { + reader.pushBack(); + break; + } + code = code << 3 | digit; + } + if (0377 < code) { + reader.error("octal escape sequence value is too large"); + } + ch = (char)code; + break; + default: + reader.error("unrecognized escape sequence"); + } + } + chars[to++] = ch; + } + return new String(chars, 0, to); + } + + private class UnicodeReader { + final int length; + int from; + int prev; + + UnicodeReader() { + this.length = String.this.length(); + this.from = 0; + this.prev = 0; + } + + int length() { + return length; + } + + boolean hasNext() { + return from < length; + } + + char next() { + prev = from; + char next = charAt(from++); + if (next != '\\' || (hasNext() && charAt(from) != 'u')) { + return next; + } + do { + next = charAt(from++); + } while (next == 'u' && hasNext()); + if (length <= from + 2) { + error("unicode escape sequence truncated at end of string"); + } + int code = (Character.digit(next , 16) << 12) | + (Character.digit(charAt(from++), 16) << 8) | + (Character.digit(charAt(from++), 16) << 4) | + Character.digit(charAt(from++), 16); + if (code < 0) { + error("unicode escape sequence contains non hexadecimal digits"); + } + return (char)code; + } + + void pushBack() { + from = prev; + } + + void error(String message) { + throw new IllegalArgumentException(message + ", pos = " + (from - 1)); + } + } + + /** * This object (which is already a string!) is itself returned. * * @return the string itself. */ public String toString() {
< prev index next >