< prev index next >

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

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

@@ -855,6 +855,85 @@
         @Override
         public int characteristics() {
             return cs;
         }
     }
+
+    static String unescape(byte[] value) throws IllegalArgumentException {
+        int length = value.length;
+        byte[] chars = new byte[length];
+        int from = 0;
+        int to = 0;
+        while (from < length) {
+            char ch = getChar(value, from++);
+            if (ch == '\\' && from < length) {
+                ch = getChar(value, from++);
+                if (ch == 'u') {
+                    while (from < length && getChar(value, from) == 'u') {
+                        from++;
+                    }
+                    if (length <= from + 3) {
+                        throw new IllegalArgumentException("unicode escape sequence truncated at end of string, pos = " + from);
+                    }
+                    int code = (Character.digit(getChar(value, from + 0), 16) << 12) |
+                               (Character.digit(getChar(value, from + 1), 16) <<  8) |
+                               (Character.digit(getChar(value, from + 2), 16) <<  4) |
+                                Character.digit(getChar(value, from + 3), 16);
+                    if (code < 0) {
+                        throw new IllegalArgumentException("unicode escape sequence contains non hexadecimal digits, pos = " + from);
+                    }
+                    if (canEncode(code)) {
+                        ch = (char)code;
+                        from += 4;
+                    } else {
+                        return StringUTF16.unescape(inflate(value, 0, length));
+                    }
+                } else {
+                    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 'u':
+                            chars[to++] = (byte)'\\';
+                            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 && from < length; i++) {
+                                int digit = Character.digit(getChar(value, from), 8);
+                                if (digit < 0) {
+                                    break;
+                                }
+                                from++;
+                                code = code << 3 | digit;
+                            }
+                            if (0377 < code) {
+                                throw new IllegalArgumentException("octal escape sequence value is too large, pos = " + from);
+                            }
+                            ch = (char)code;
+                            break;
+                        default:
+                            throw new IllegalArgumentException("unrecognized escape sequence, pos = " + from);
+                    }
+                }
+            }
+            chars[to++] = (byte)ch;
+        }
+        return new String(Arrays.copyOfRange(chars, 0, to), LATIN1);
+    }
+
 }
< prev index next >