You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ba...@apache.org on 2013/10/26 04:45:39 UTC

svn commit: r1535914 - in /commons/proper/lang/trunk/src: main/java/org/apache/commons/lang3/text/translate/OctalUnescaper.java test/java/org/apache/commons/lang3/text/translate/OctalUnescaperTest.java

Author: bayard
Date: Sat Oct 26 02:45:39 2013
New Revision: 1535914

URL: http://svn.apache.org/r1535914
Log:
Rewriting OctalUnescaper as a hand rolled parser (all of 4 characters), instead of trying to handle the conversion via repeated attempts to convert the numbers. This fixes bugs, see LANG-929, and also changes the behaviour for 'illegal' octals such as \999. Instead of throwing NumberFormatException, it will now ignore them. This seems the better behaviour. 

Modified:
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/text/translate/OctalUnescaper.java
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/text/translate/OctalUnescaperTest.java

Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/text/translate/OctalUnescaper.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/text/translate/OctalUnescaper.java?rev=1535914&r1=1535913&r2=1535914&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/text/translate/OctalUnescaper.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/text/translate/OctalUnescaper.java Sat Oct 26 02:45:39 2013
@@ -40,25 +40,34 @@ public class OctalUnescaper extends Char
      */
     @Override
     public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
-        if(input.charAt(index) == '\\' && index < (input.length() - 1) && Character.isDigit(input.charAt(index + 1)) ) {
-            final int start = index + 1;
+        int remaining = input.length() - index - 1; // how many characters left, ignoring the first \
+        StringBuilder builder = new StringBuilder();
+        if(input.charAt(index) == '\\' && remaining > 0 && isOctalDigit(input.charAt(index + 1)) ) {
+            int next = index + 1;
+            int next2 = index + 2;
+            int next3 = index + 3;
 
-            int end = index + 2;
-            while ( end < input.length() && Character.isDigit(input.charAt(end)) ) {
-                end++;
-                if ( Integer.parseInt(input.subSequence(start, end).toString(), 10) > OCTAL_MAX) {
-                    end--; // rollback
-                    break;
-                }
-                // only 3 characters applicable for Octal
-                if (end - start >= 3) {
-                    break;
+            // we know this is good as we checked it in the if block above
+            builder.append(input.charAt(next));
+
+            if(remaining > 1 && isOctalDigit(input.charAt(next2))) {
+                builder.append(input.charAt(next2));
+                if(remaining > 2 && isZeroToThree(input.charAt(next)) && isOctalDigit(input.charAt(next3))) {
+                    builder.append(input.charAt(next3));
                 }
             }
 
-            out.write( Integer.parseInt(input.subSequence(start, end).toString(), 8) );
-            return 1 + end - start;
+            out.write( Integer.parseInt(builder.toString(), 8) );
+            return 1 + builder.length();
         }
         return 0;
     }
+
+    private boolean isOctalDigit(char ch) {
+        return ch >= '0' && ch <= '7';
+    }
+
+    private boolean isZeroToThree(char ch) {
+        return ch >= '0' && ch <= '3';
+    }
 }

Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/text/translate/OctalUnescaperTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/text/translate/OctalUnescaperTest.java?rev=1535914&r1=1535913&r2=1535914&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/text/translate/OctalUnescaperTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/text/translate/OctalUnescaperTest.java Sat Oct 26 02:45:39 2013
@@ -69,19 +69,14 @@ public class OctalUnescaperTest {
         input = "\\0003";
         result = oue.translate(input);
         assertEquals("Failed to unescape octal characters via the between method", "\000" + "3", result);
-    }
 
-    @Test
-    public void testOutOfRange() {
-        final OctalUnescaper oue = new OctalUnescaper();
+        input = "\\279";
+        result = oue.translate(input);
+        assertEquals("Failed to unescape octal characters via the between method", "\279", result);
 
-        String input = "\\999";
-        try {
-            String result = oue.translate(input);
-            fail("NumberFormatException was expected for input: " + input);
-        } catch(NumberFormatException nfe) {
-            // expected
-        }
+        input = "\\999";
+        result = oue.translate(input);
+        assertEquals("Failed to ignore an out of range octal character via the between method", "\\999", result);
     }
 
 }