< prev index next >

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

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

@@ -1546,6 +1546,79 @@
 
     public static void checkBoundsOffCount(int offset, int count, byte[] val) {
         String.checkBoundsOffCount(offset, count, length(val));
     }
 
+    static String unescape(byte[] value) throws IllegalArgumentException {
+        int length = value.length >>> 1;
+        char[] chars = new char[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);
+                    }
+                    ch = (char)code;
+                    from += 4;
+                } 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++] = '\\';
+                            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++] = ch;
+        }
+        return new String(chars, 0, to);
+    }
 }
< prev index next >