changeset 49310:ad490b781dac raw-string-literal

0000000: Updating library support
author jlaskey
date Fri, 02 Mar 2018 14:33:07 -0500
parents 78fd7a296cd8
children 64f68718c2f7
files src/java.base/share/classes/java/lang/String.java src/java.base/share/classes/java/lang/StringLatin1.java src/java.base/share/classes/java/lang/StringUTF16.java test/jdk/java/lang/String/RawStringLiteralLib.java
diffstat 4 files changed, 438 insertions(+), 227 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/String.java	Thu Feb 15 22:07:11 2018 +0100
+++ b/src/java.base/share/classes/java/lang/String.java	Fri Mar 02 14:33:07 2018 -0500
@@ -37,7 +37,6 @@
 import java.util.Objects;
 import java.util.Spliterator;
 import java.util.StringJoiner;
-import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 import java.util.stream.IntStream;
@@ -1779,7 +1778,7 @@
      * @param   src         the characters being searched.
      * @param   srcCoder    coder handles the mapping between bytes/chars
      * @param   srcCount    count of the source string.
-     * @param   tgt         the characters being searched for.
+     * @param   tgtStr      the characters being searched for.
      * @param   fromIndex   the index to begin searching from.
      */
     static int lastIndexOf(byte[] src, byte srcCoder, int srcCount,
@@ -2599,8 +2598,8 @@
     }
 
     /**
-     * Returns a string whose value is this string, with any leading and trailing
-     * whitespace removed.
+     * Returns a string whose value is this string, with all leading
+     * and trailing white space removed.
      * <p>
      * If this {@code String} object represents an empty character
      * sequence, or the first and last characters of character sequence
@@ -2622,12 +2621,12 @@
      * character at index <i>m</i>-that is, the result of
      * {@code this.substring(k, m + 1)}.
      * <p>
-     * This method may be used to trim whitespace (as defined above) from
+     * This method may be used to trim white space (as defined above) from
      * the beginning and end of a string.
      *
-     * @return  A string whose value is this string, with any leading and trailing white
-     *          space removed, or this string if it has no leading or
-     *          trailing white space.
+     * @return  a string whose value is this string, with all leading
+     *          and trailing white space removed, or this string if it
+     *          has no leading or trailing white space.
      */
     public String trim() {
         String ret = isLatin1() ? StringLatin1.trim(value)
@@ -2636,8 +2635,8 @@
     }
 
     /**
-     * Returns a string whose value is this string, with any leading
-     * whitespace removed.
+     * Returns a string whose value is this string, with all leading
+     * white space removed.
      * <p>
      * If this {@code String} object represents an empty character
      * sequence, or the first characters of character sequence
@@ -2658,12 +2657,12 @@
      * character at index <i>m</i>-that is, the result of
      * {@code this.substring(k, m + 1)}.
      * <p>
-     * This method may be used to trim whitespace (as defined above) from
+     * This method may be used to trim white space (as defined above) from
      * the beginning of a string.
      *
-     * @return  A string whose value is this string, with any leading white
+     * @return  a string whose value is this string, with all leading white
      *          space removed, or this string if it has no leading white space.
-     * @since 10
+     * @since 11
      */
     public String trimLeft() {
         String ret = isLatin1() ? StringLatin1.trimLeft(value)
@@ -2672,8 +2671,8 @@
     }
 
     /**
-     * Returns a string whose value is this string, with any trailing
-     * whitespace removed.
+     * Returns a string whose value is this string, with all trailing
+     * white space removed.
      * <p>
      * If this {@code String} object represents an empty character
      * sequence, or the last characters of character sequence
@@ -2695,13 +2694,13 @@
      * character at index <i>m</i>-that is, the result of
      * {@code this.substring(k, m + 1)}.
      * <p>
-     * This method may be used to trim whitespace (as defined above) from
+     * This method may be used to trim white space (as defined above) from
      * the end of a string.
      *
-     * @return  A string whose value is this string, with any trailing white
+     * @return  a string whose value is this string, with all trailing white
      *          space removed, or this string if it has no
      *          trailing white space.
-     * @since 10
+     * @since 11
      */
     public String trimRight() {
         String ret = isLatin1() ? StringLatin1.trimRight(value)
@@ -2709,69 +2708,65 @@
         return ret == null ? this : ret;
     }
 
-    private int skipLeadingSpaces() {
-        if (isLatin1()) {
-            return StringLatin1.skipLeadingSpaces(value);
-        } else {
-            return StringUTF16.skipLeadingSpaces(value) >> 1;
-        }
-    }
-
-    private String trimJoin(String[] lines) {
-        int length = lines.length;
-        StringBuilder sb = new StringBuilder(length());
-        int first = lines[0].isEmpty() ? 1 : 0;
-        int last = lines[length - 1].isEmpty() ? length - 1 : length;
-        for (int i = first; i < last; i++) {
-            if (i != first) {
-                sb.append('\n');
-            }
-            sb.append(lines[i]);
-        }
-        return sb.toString();
+    /**
+     * Splits this string at line separators into a String array.
+     * <p>
+     * The array returned by this method contains each line of this
+     * string that is terminated by a line separator or end of
+     * string. The lines in the array are in the order in which
+     * they occur in this string and do not include the line
+     * separator.
+     * <p>
+     * Line separators recognized are {@code "\n", "\r\n"}
+     * and {@code "\r"}.
+     *
+     * @return  the array of strings computed by splitting this
+     *          string at line separators
+     * @since 11
+     */
+    public String[] lines() {
+        return isLatin1() ? StringLatin1.lines(value)
+                          : StringUTF16.lines(value);
     }
 
     /**
-     * When applied to multi-line strings, removes trailing spaces
+     * Replaces line separators in the string with the
+     * system-dependent line separator returned by
+     * {@code System.lineSeparator()}
+     * <p>
+     * Line separators recognized are {@code "\n", "\r\n"}
+     * and {@code "\r"}.
+     *
+     * @return  a copy of this string with line separators
+     *          replaced with the system-dependent line separator
+     * @since 11
+     */
+    public String useLineSeparator() {
+        return join(System.lineSeparator(), lines());
+    }
+
+    /**
+     * When applied to multi-line strings, determines the
+     * minimal number of leading white spaces of each line
+     * and then removes that minimum number of characters
      * from each line.
      * <p>
-     * The new line terminator should {@code '\n'}.
+     * Trailing white space is always removed.
+     * <p>
+     * Line separators are replaced with {@code "\n"}
      * <p>
      * If the first line is blank then it is removed.
      * <p>
      * If the last line is blank then it is removed.
-     * @return String with trailing spaces removed.
-     * @since 10
-     */
-    public java.lang.String trimLines() {
-        if (isEmpty()) {
-            return this;
-        }
-        java.lang.String[] lines = split("\n");
-        for (int i = 0; i < lines.length; i++) {
-            lines[i] = lines[i].trimRight();
-        }
-        return trimJoin(lines);
-    }
-
-    /**
-     * When applied to multi-line strings, determines the minimal number of
-     * leading spaces of each line and then removes that minimum from each
-     * line.
-     * <p>
-     * The new line terminator should {@code '\n'}.
-     * <p>
-     * If the first line is blank then it is removed.
-     * <p>
-     * If the last line is blank then it is removed.
+     *
      * @return String with indent removed.
-     * @since 10
+     * @since 11
      */
     public String trimIndent() {
         if (isEmpty()) {
             return this;
         }
-        String[] lines = split("\n");
+        String[] lines = lines();
         int count = lines.length;
         int least = Integer.MAX_VALUE;
         for (int i = 0; i < count; i++) {
@@ -2796,47 +2791,141 @@
         return trimJoin(lines);
     }
 
+    private String trimJoin(String[] lines) {
+        int length = lines.length;
+        StringBuilder sb = new StringBuilder(length());
+        int first = lines[0].isEmpty() ? 1 : 0;
+        int last = lines[length - 1].isEmpty() ? length - 1 : length;
+        for (int i = first; i < last; i++) {
+            if (i != first) {
+                sb.append('\n');
+            }
+            sb.append(lines[i]);
+        }
+        return sb.toString();
+    }
+
+    private int skipLeadingSpaces() {
+        if (isLatin1()) {
+            return StringLatin1.skipLeadingSpaces(value);
+        } else {
+            return StringUTF16.skipLeadingSpaces(value) >> 1;
+        }
+    }
+
     /**
-     * When applied to multi-line strings, removes leading whitespace up to
-     * marker from each line.
+     * When applied to multi-line strings selectively removes
+     * margin characters from the beginning and end of each line.
      * <p>
-     * The new line terminator should {@code '\n'}.
+     * Two marker strings provide control over how each line is
+     * trimmed, one for the beginning of the line and one for
+     * the end.
      * <p>
-     * If the first line is blank then it is removed.
+     * If begin marker {@code beginMarker} is the empty string
+     * then the left margin is uneffected. If the begin marker
+     * is a single space, then all leading white space is removed.
+     * Otherwise, if the begin marker is found, all characters
+     * between the line start of the end of the first
+     * occurrence of the begin marker are removed.
      * <p>
-     * If the last line is blank then it is removed.
-     * @param marker String representing margin indicator.
-     * @return String with margin removed.
-     * @since 10
+     * If end marker {@code endMarker} is the empty string
+     * then the right margin is uneffected. If the end marker
+     * is a single space, then all trailing white space is removed.
+     * Otherwise, if the end marker is found, all characters
+     * between the last occurrence of the end marker and the
+     * end of line are removed.
+     * <p>
+     * Line separators are replaced with {@code "\n"}. If the first
+     * line is blank then it is removed. If the last line is blank
+     * then it is removed.
+     *
+     * @param  beginMarker  string representing left margin indicator
+     * @param  endMarker    string representing right margin indicator
+     * @return  string with margins removed
+     * @since 11
      */
-    public String trimMargin(String marker) {
+    public String trimMargins(String beginMarker, String endMarker) {
+        Objects.requireNonNull(beginMarker);
+        Objects.requireNonNull(endMarker);
         if (isEmpty()) {
             return this;
         }
-        String[] lines = split("\n");
-        int count = lines.length;
-        int trim = marker.length();
-        for (int i = 0; i < count; i++) {
-            String line = lines[i].trimLeft();
-            if (line.startsWith(marker)) {
-                line = line.substring(trim);
+        boolean hasBeginTrim = !beginMarker.isEmpty();
+        boolean isTrimLeft = " ".equals(beginMarker);
+        int beginLength = beginMarker.length();
+        boolean hasEndTrim = !endMarker.isEmpty();
+        boolean isTrimRight = " ".equals(endMarker);
+        int endLength = endMarker.length();
+        String[] lines = lines();
+
+        for (int i = 0; i < lines.length; i++) {
+            String line = lines[i];
+            if (hasBeginTrim) {
+                line = line.trimLeft();
+                if (!isTrimLeft && line.startsWith(beginMarker)) {
+                    line = line.substring(beginLength);
+                }
             }
-            lines[i] = line.trimRight();
+            if (hasEndTrim) {
+                line = line.trimRight();
+                if (!isTrimRight && line.endsWith(endMarker)) {
+                    line = line.substring(0, line.length() - endLength);
+                }
+            }
+            lines[i] = line;
         }
         return trimJoin(lines);
     }
 
     /**
-     * When applied to multi-line strings, removes leading whitespace up to
-     * the first "|" from each line.
+     * When applied to multi-line strings selectively removes
+     * margin characters from the beginning of each line.
      * <p>
-     * If the first line is blank then it is removed.
+     * The marker string provided controls over how each line is
+     * trimmed.
      * <p>
-     * If the last line is blank then it is removed.
-     * @return String with margin removed.
+     * If the marker {@code marker} is the empty string then
+     * the left margin is uneffected. If the marker is a
+     * single space, then all leading white space is removed.
+     * Otherwise, if the marker is found, all characters
+     * between the line start of the end of the first
+     * occurrence of the marker are removed.
+     * <p>
+     * Trailing white space is always removed.
+     * <p>
+     * Line separators are replaced with {@code "\n"}. If the first
+     * line is blank then it is removed. If the last line is blank
+     * then it is removed.
+     *
+     * @param  marker  String representing margin indicator
+     * @return  string with margins removed
+     * @since 11
      */
-    public String trimMargin() {
-        return trimMargin("|");
+    public String trimMargins(String marker) {
+        Objects.requireNonNull(marker);
+        return trimMargins(marker, " ");
+    }
+
+    /**
+     * When applied to multi-line strings removes white space
+     * from the beginning and end of each line.
+     * <p>
+     * Line separators are replaced with {@code "\n"}. If the first
+     * line is blank then it is removed. If the last line is blank
+     * then it is removed.
+     *
+     * @return  string with margins removed
+     * @since 11
+     */
+    public String trimMargins() {
+        if (isEmpty()) {
+            return this;
+        }
+        String[] lines = lines();
+        for (int i = 0; i < lines.length; i++) {
+            lines[i] = lines[i].trim();
+        }
+        return trimJoin(lines);
     }
 
     /**
@@ -3486,4 +3575,5 @@
                 "begin " + begin + ", end " + end + ", length " + length);
         }
     }
+
 }
--- a/src/java.base/share/classes/java/lang/StringLatin1.java	Thu Feb 15 22:07:11 2018 +0100
+++ b/src/java.base/share/classes/java/lang/StringLatin1.java	Fri Mar 02 14:33:07 2018 -0500
@@ -26,6 +26,7 @@
 package java.lang;
 
 import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.Formatter;
 import java.util.Locale;
 import java.util.Objects;
@@ -552,6 +553,29 @@
                 newString(value, 0, right) : null;
     }
 
+    static String[] lines(byte[] value) {
+        ArrayList<String> list = new ArrayList<>();
+        int length = value.length;
+        int start = 0;
+        for (int i = 0; i < length; i++) {
+            byte ch = value[i];
+            if (ch != '\n' && ch != '\r') {
+                continue;
+            }
+            int end = i;
+            if (ch == '\r') {
+                int j = i + 1;
+                if (j != length && value[j] =='\n') {
+                    i = j;
+                }
+            }
+            list.add(newString(value, start, end - start));
+            start = i + 1;
+        }
+        list.add(newString(value, start, length - start));
+        return list.toArray(new String[list.size()]);
+    }
+
     public static void putChar(byte[] val, int index, int c) {
         //assert (canEncode(c));
         val[index] = (byte)(c);
--- a/src/java.base/share/classes/java/lang/StringUTF16.java	Thu Feb 15 22:07:11 2018 +0100
+++ b/src/java.base/share/classes/java/lang/StringUTF16.java	Fri Mar 02 14:33:07 2018 -0500
@@ -26,6 +26,7 @@
 package java.lang;
 
 import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.Formatter;
 import java.util.Locale;
 import java.util.Spliterator;
@@ -818,52 +819,76 @@
     }
 
     public static int skipLeadingSpaces(byte[] value) {
+        int length = value.length >> 1;
         int left = 0;
-        while ((left < value.length) &&
-                (value[left + 1] == 0) &&
-                ((value[left] & 0xff) <= ' ')) {
-            left += 2;
+        while (left < length && getChar(value, left) <= ' ') {
+            left++;
         }
         return left;
     }
 
     public static int skipTrailingSpaces(byte[] value) {
-        int right = value.length;
-        while ((0 < right) &&
-                (value[right - 1] == 0) &&
-                ((value[right - 2] & 0xff) <= ' ')) {
-            right -= 2;
+        int length = value.length >> 1;
+        int right = length;
+        while (0 < right && getChar(value, right - 1) <= ' ') {
+            right--;
         }
         return right;
     }
 
     public static String trim(byte[] value) {
+        int length = value.length >> 1;
         int left = skipLeadingSpaces(value);
-        if (left == value.length) {
+        if (left == length) {
             return "";
         }
         int right = skipTrailingSpaces(value);
-        return ((left > 0) || (right < value.length)) ?
-                new String(Arrays.copyOfRange(value, left, right), UTF16) : null;
+        return ((left > 0) || (right < length)) ?
+               new String(Arrays.copyOfRange(value, left << 1, right << 1), UTF16) : null;
     }
 
     public static String trimLeft(byte[] value) {
+        int length = value.length >> 1;
         int left = skipLeadingSpaces(value);
-        if (left == value.length) {
+        if (left == length) {
             return "";
         }
         return (left != 0) ?
-                new String(Arrays.copyOfRange(value, left, value.length), UTF16) :
+                new String(Arrays.copyOfRange(value, left << 1, value.length), UTF16) :
                 null;
     }
 
     public static String trimRight(byte[] value) {
+        int length = value.length >> 1;
         int right = skipTrailingSpaces(value);
         if (right == 0) {
             return "";
         }
-        return (right != value.length) ?
-                new String(Arrays.copyOfRange(value, 0, right), UTF16) : null;
+        return (right != length) ?
+                new String(Arrays.copyOfRange(value, 0, right << 1), UTF16) : null;
+    }
+
+    static String[] lines(byte[] value) {
+        ArrayList<String> list = new ArrayList<>();
+        int length = value.length >> 1;
+        int start = 0;
+        for (int i = 0; i < length; i++) {
+            char ch = getChar(value, i);
+            if (ch != '\n' && ch != '\r') {
+                continue;
+            }
+            int end = i;
+            if (ch == '\r') {
+                int j = i + 1;
+                if (j != length && getChar(value, j) =='\n') {
+                    i = j;
+                }
+            }
+            list.add(newString(value, start, end - start));
+            start = i + 1;
+        }
+        list.add(newString(value, start, length - start));
+        return list.toArray(new String[list.size()]);
     }
 
     private static void putChars(byte[] val, int index, char[] str, int off, int end) {
--- a/test/jdk/java/lang/String/RawStringLiteralLib.java	Thu Feb 15 22:07:11 2018 +0100
+++ b/test/jdk/java/lang/String/RawStringLiteralLib.java	Fri Mar 02 14:33:07 2018 -0500
@@ -43,48 +43,112 @@
         EQ("   abc   ".trim(), "abc");
         EQ("   abc   ".trimLeft(), "abc   ");
         EQ("   abc   ".trimRight(), "   abc");
+        EQ("   abc\u2022   ".trim(), "abc\u2022");
+        EQ("   abc\u2022   ".trimLeft(), "abc\u2022   ");
+        EQ("   abc\u2022   ".trimRight(), "   abc\u2022");
         EQ("".trim(), "");
         EQ("".trimLeft(), "");
         EQ("".trimRight(), "");
 
+        // trimIndent
         for (String prefix : List.of("", "\n", "   \n"))
         for (String suffix : List.of("", "\n", "   \n"))
-        for (String insert : List.of("", "xyz", "   xyz", "xyz   ", "   xyz   ", "   // comment"))
+        for (String middle : List.of("",
+                                     "xyz",
+                                     "   xyz",
+                                     "xyz   ",
+                                     "   xyz   ",
+                                     "xyz\u2022",
+                                     "   xyz\u2022",
+                                     "xyz\u2022   ",
+                                     "   xyz\u2022   ",
+                                     "   // comment"))
         {
-            // trimLines
-            EQ((prefix + "   abc   \n" + insert + "\n   def   \n" + suffix).trimLines(),
-                "   abc\n" + insert.trimRight() + "\n   def");
+            String input = prefix + "   abc   \n" + middle + "\n   def   \n" + suffix;
+            String[] inputLines = input.lines();
+            int inputLength = inputLines.length;
+            String output = input.trimIndent();
+            String[] outputLines = output.lines();
+            int outputLength = outputLines.length;
 
-            // trimIndent
-            if (prefix.isEmpty()) {
-                if (insert.isEmpty()) {
-                    EQ(("   abc   \n" + insert + "\n   def   \n" + suffix).trimIndent(),
-                        "   abc\n" + insert.trimRight() + "\ndef");
-                } else if (insert.startsWith("   ")) {
-                    EQ(("   abc   \n" + insert + "\n   def   \n" + suffix).trimIndent(),
-                        "   abc\n" + insert.trimRight().substring(3) + "\ndef");
+            int start = inputLines[0].trim().isEmpty() ? 1 : 0;
+            int end = inputLines[inputLength - 1].trim().isEmpty() ? inputLength - 1 : inputLength;
+
+            if (outputLength != (end - start)) {
+                report("Wrong number of lines", "Input:", input, "Output:", output);
+            }
+            int indent = 0;
+            for (int i = 0; i < outputLength; i++) {
+                String line = outputLines[i];
+                int offset = inputLines[start + i].indexOf(line);
+                if (offset == -1) {
+                    report("Loss of lines", "Input:", input, "Output:", output);
+                }
+                if (i == 0) {
+                    indent = offset;
+                } else if (offset != indent ) {
+                    report("Inconsistent indent", "Input:", input, "Output:", output);
+                }
+            }
+        }
+
+        // trimMargin
+        for (String prefix : List.of("", "\n", "   \n"))
+        for (String suffix : List.of("", "\n", "   \n"))
+        for (String middle : List.of("",
+                                     "xyz",
+                                     "   xyz",
+                                     "xyz   ",
+                                     "   xyz   ",
+                                     "xyz\u2022",
+                                     "   xyz\u2022",
+                                     "xyz\u2022   ",
+                                     "   xyz\u2022   ",
+                                     "   // comment"))
+        for (String leftMargin : List.of("", " ", "|", "   |"))
+        for (String rightMargin : List.of("", " ", "|", "|   "))
+        {
+            String input = prefix +
+                           leftMargin + "   abc   " + rightMargin + "\n" +
+                           leftMargin + middle + rightMargin + "\n" +
+                           leftMargin + "   def   " + rightMargin + "\n" +
+                           suffix;
+            String[] inputLines = input.lines();
+            int inputLength = inputLines.length;
+            String output;
+
+            if (leftMargin.isEmpty() && rightMargin.isEmpty()) {
+                output = input.trimMargins();
+            } else {
+                String beginMarker = leftMargin.contains("|") ? "|" : leftMargin;
+                String endMarker = rightMargin.contains("|") ? "|" : rightMargin;
+
+                if (" ".equals(endMarker)) {
+                    output = input.trimMargins(beginMarker);
                 } else {
-                    EQ(("   abc   \n" + insert + "\n   def   \n" + suffix).trimIndent(),
-                        "   abc\n" + insert.trimRight() + "\n   def");
-                }
-            } else {
-                if (insert.isEmpty()) {
-                    EQ((prefix + "   abc   \n" + insert + "\n   def   \n" + suffix).trimIndent(),
-                        "abc\n" + insert.trimRight() + "\ndef");
-                } else if (insert.startsWith("   ")) {
-                    EQ(("   abc   \n" + insert + "\n   def   \n" + suffix).trimIndent(),
-                        "   abc\n" + insert.trimRight().substring(3) + "\ndef");
-                } else {
-                    EQ((prefix + "   abc   \n" + insert + "\n   def   \n" + suffix).trimIndent(),
-                        "   abc\n" + insert.trimRight() + "\n   def");
+                    output = input.trimMargins(beginMarker, endMarker);
                 }
             }
 
-            // trimMargin
-            EQ((prefix + "   | abc   \n   | " + insert + "\n   | def   \n" + suffix).trimMargin(),
-                " abc\n" + (" " + insert).trimRight() + "\n def");
-            EQ((prefix + "   # abc   \n   # " + insert + "\n   # def   \n" + suffix).trimMargin("#"),
-                " abc\n" + (" " + insert).trimRight() + "\n def");
+            String[] outputLines = output.lines();
+            int outputLength = outputLines.length;
+
+            int start = inputLines[0].trim().isEmpty() ? 1 : 0;
+            int end = inputLines[inputLength - 1].trim().isEmpty() ? inputLength - 1 : inputLength;
+
+            if (outputLength != (end - start)) {
+                report("Wrong number of lines", "Input:", input, "Output:", output);
+            }
+            int indent = 0;
+            for (int i = 0; i < outputLength; i++) {
+                String line = outputLines[i];
+                if (!inputLines[start + i].contains(line)) {
+                    report("Loss of lines", "Input:", input, "Output:", output);
+                }
+                if (line.indexOf('|') != -1) {
+                    report("Margin not removed", "Input:", input, "Output:", output);
+                }
+            }
         }
     }
 
@@ -160,112 +224,120 @@
      * Test for MalformedEscapeException.
      */
     static void test3() {
-        WELLFORMED(`\b`);
-        WELLFORMED(`\f`);
-        WELLFORMED(`\n`);
-        WELLFORMED(`\r`);
-        WELLFORMED(`\t`);
-        WELLFORMED(`\0`);
-        WELLFORMED(`\7`);
-        WELLFORMED(`\12`);
-        WELLFORMED(`\012`);
-        WELLFORMED(`\u0000`);
-        WELLFORMED(`\u2022`);
-        WELLFORMED(`•\b`);
-        WELLFORMED(`•\f`);
-        WELLFORMED(`•\n`);
-        WELLFORMED(`•\r`);
-        WELLFORMED(`•\t`);
-        WELLFORMED(`•\0`);
-        WELLFORMED(`•\7`);
-        WELLFORMED(`•\12`);
-        WELLFORMED(`•\012`);
-        WELLFORMED(`•\u0000`);
-        WELLFORMED(`•\u2022`);
+        wellFormed(`\b`);
+        wellFormed(`\f`);
+        wellFormed(`\n`);
+        wellFormed(`\r`);
+        wellFormed(`\t`);
+        wellFormed(`\0`);
+        wellFormed(`\7`);
+        wellFormed(`\12`);
+        wellFormed(`\012`);
+        wellFormed(`\u0000`);
+        wellFormed(`\u2022`);
+        wellFormed(`•\b`);
+        wellFormed(`•\f`);
+        wellFormed(`•\n`);
+        wellFormed(`•\r`);
+        wellFormed(`•\t`);
+        wellFormed(`•\0`);
+        wellFormed(`•\7`);
+        wellFormed(`•\12`);
+        wellFormed(`•\012`);
+        wellFormed(`•\u0000`);
+        wellFormed(`•\u2022`);
 
-        MALFORMED(`\x`);
-        MALFORMED(`\+`);
-        MALFORMED(`\u`);
-        MALFORMED(`\uuuuu`);
-        MALFORMED(`\u2`);
-        MALFORMED(`\u20`);
-        MALFORMED(`\u202`);
-        MALFORMED(`\u2   `);
-        MALFORMED(`\u20  `);
-        MALFORMED(`\u202 `);
-        MALFORMED(`\uuuuu2`);
-        MALFORMED(`\uuuuu20`);
-        MALFORMED(`\uuuuu202`);
-        MALFORMED(`\uuuuu2   `);
-        MALFORMED(`\uuuuu20  `);
-        MALFORMED(`\uuuuu202 `);
-        MALFORMED(`\uG`);
-        MALFORMED(`\u2G`);
-        MALFORMED(`\u20G`);
-        MALFORMED(`\uG   `);
-        MALFORMED(`\u2G  `);
-        MALFORMED(`\u20G `);
-        MALFORMED(`\uuuuuG`);
-        MALFORMED(`\uuuuu2G`);
-        MALFORMED(`\uuuuu20G`);
-        MALFORMED(`\uuuuuG   `);
-        MALFORMED(`\uuuuu2G  `);
-        MALFORMED(`\uuuuu20G `);
+        malformed(`\x`);
+        malformed(`\+`);
+        malformed(`\u`);
+        malformed(`\uuuuu`);
+        malformed(`\u2`);
+        malformed(`\u20`);
+        malformed(`\u202`);
+        malformed(`\u2   `);
+        malformed(`\u20  `);
+        malformed(`\u202 `);
+        malformed(`\uuuuu2`);
+        malformed(`\uuuuu20`);
+        malformed(`\uuuuu202`);
+        malformed(`\uuuuu2   `);
+        malformed(`\uuuuu20  `);
+        malformed(`\uuuuu202 `);
+        malformed(`\uG`);
+        malformed(`\u2G`);
+        malformed(`\u20G`);
+        malformed(`\uG   `);
+        malformed(`\u2G  `);
+        malformed(`\u20G `);
+        malformed(`\uuuuuG`);
+        malformed(`\uuuuu2G`);
+        malformed(`\uuuuu20G`);
+        malformed(`\uuuuuG   `);
+        malformed(`\uuuuu2G  `);
+        malformed(`\uuuuu20G `);
 
-        MALFORMED(`•\x`);
-        MALFORMED(`•\+`);
-        MALFORMED(`•\u`);
-        MALFORMED(`•\uuuuu`);
-        MALFORMED(`•\u2`);
-        MALFORMED(`•\u20`);
-        MALFORMED(`•\u202`);
-        MALFORMED(`•\u2   `);
-        MALFORMED(`•\u20  `);
-        MALFORMED(`•\u202 `);
-        MALFORMED(`•\uuuuu2`);
-        MALFORMED(`•\uuuuu20`);
-        MALFORMED(`•\uuuuu202`);
-        MALFORMED(`•\uuuuu2   `);
-        MALFORMED(`•\uuuuu20  `);
-        MALFORMED(`•\uuuuu202 `);
-        MALFORMED(`•\uG`);
-        MALFORMED(`•\u2G`);
-        MALFORMED(`•\u20G`);
-        MALFORMED(`•\uG   `);
-        MALFORMED(`•\u2G  `);
-        MALFORMED(`•\u20G `);
-        MALFORMED(`•\uuuuuG`);
-        MALFORMED(`•\uuuuu2G`);
-        MALFORMED(`•\uuuuu20G`);
-        MALFORMED(`•\uuuuuG   `);
-        MALFORMED(`•\uuuuu2G  `);
-        MALFORMED(`•\uuuuu20G `);
+        malformed(`•\x`);
+        malformed(`•\+`);
+        malformed(`•\u`);
+        malformed(`•\uuuuu`);
+        malformed(`•\u2`);
+        malformed(`•\u20`);
+        malformed(`•\u202`);
+        malformed(`•\u2   `);
+        malformed(`•\u20  `);
+        malformed(`•\u202 `);
+        malformed(`•\uuuuu2`);
+        malformed(`•\uuuuu20`);
+        malformed(`•\uuuuu202`);
+        malformed(`•\uuuuu2   `);
+        malformed(`•\uuuuu20  `);
+        malformed(`•\uuuuu202 `);
+        malformed(`•\uG`);
+        malformed(`•\u2G`);
+        malformed(`•\u20G`);
+        malformed(`•\uG   `);
+        malformed(`•\u2G  `);
+        malformed(`•\u20G `);
+        malformed(`•\uuuuuG`);
+        malformed(`•\uuuuu2G`);
+        malformed(`•\uuuuu20G`);
+        malformed(`•\uuuuuG   `);
+        malformed(`•\uuuuu2G  `);
+        malformed(`•\uuuuu20G `);
+    }
+
+    /*
+     * Report difference in result.
+     */
+    static void report(String message, String inputTag, String input,
+                                       String outputTag, String output) {
+        System.err.println(message);
+        System.err.println();
+        System.err.println(inputTag);
+        System.err.println(input.replaceAll(" ", "."));
+        System.err.println();
+        System.err.println(outputTag);
+        System.err.println(output.replaceAll(" ", "."));
+        throw new RuntimeException();
     }
 
     /*
      * Raise an exception if the two inputs are not equivalent.
      */
-    static void EQ(String input, String expected) {
+    static void equal(String input, String expected) {
         if (input == null || expected == null || !expected.equals(input)) {
-            System.err.println("Failed EQ");
-            System.err.println();
-            System.err.println("Input:");
-            System.err.println(input.replaceAll(" ", "."));
-            System.err.println();
-            System.err.println("Expected:");
-            System.err.println(expected.replaceAll(" ", "."));
-            throw new RuntimeException();
+            report("Failed EQ", "Input:", input, "Expected:", expected);
         }
     }
 
     /*
      * Raise an exception if the string contains a malformed escape.
      */
-    static void WELLFORMED(String rawString) {
+    static void wellFormed(String rawString) {
         try {
             rawString.unescape();
         } catch (MalformedEscapeException ex) {
-            System.err.println("Failed WELLFORMED");
+            System.err.println("Failed wellFormed");
             System.err.println(rawString);
             throw new RuntimeException();
         }
@@ -274,10 +346,10 @@
     /*
      * Raise an exception if the string does not contain a malformed escape.
      */
-    static void MALFORMED(String rawString) {
+    static void malformed(String rawString) {
         try {
             rawString.unescape();
-            System.err.println("Failed MALFORMED");
+            System.err.println("Failed malformed");
             System.err.println(rawString);
             throw new RuntimeException();
         } catch (MalformedEscapeException ex) {