You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mime4j-dev@james.apache.org by ol...@apache.org on 2009/12/24 18:29:58 UTC

svn commit: r893789 - in /james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/codec: Base64InputStream.java QuotedPrintableInputStream.java

Author: olegk
Date: Thu Dec 24 17:29:58 2009
New Revision: 893789

URL: http://svn.apache.org/viewvc?rev=893789&view=rev
Log:
MIME4J-103: QuotedPrintableInputStream refactoring (third round); eliminated double buffering of decoded data

Modified:
    james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/codec/Base64InputStream.java
    james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableInputStream.java

Modified: james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/codec/Base64InputStream.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/codec/Base64InputStream.java?rev=893789&r1=893788&r2=893789&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/codec/Base64InputStream.java (original)
+++ james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/codec/Base64InputStream.java Thu Dec 24 17:29:58 2009
@@ -120,7 +120,7 @@
         if (length == 0)
             return 0;
 
-        return read0(buffer, offset, offset + length);
+        return read0(buffer, offset, length);
     }
 
     @Override
@@ -131,16 +131,17 @@
         closed = true;
     }
 
-    private int read0(final byte[] buffer, final int from, final int to)
-            throws IOException {
-        int index = from; // index into given buffer
+    private int read0(final byte[] buffer, final int off, final int len) throws IOException {
+        int from = off;
+        int to = off + len;
+        int index = off;
 
         // check if a previous invocation left decoded content
         if (decodedBuf.length() > 0) {
-            int len = Math.min(decodedBuf.length(), to - from);
-            System.arraycopy(decodedBuf.buffer(), 0, buffer, index, len);
-            decodedBuf.remove(0, len);
-            index += len;
+            int chunk = Math.min(decodedBuf.length(), len);
+            System.arraycopy(decodedBuf.buffer(), 0, buffer, index, chunk);
+            decodedBuf.remove(0, chunk);
+            index += chunk;
         }
 
         // eof or pad reached?

Modified: james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableInputStream.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableInputStream.java?rev=893789&r1=893788&r2=893789&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableInputStream.java (original)
+++ james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableInputStream.java Thu Dec 24 17:29:58 2009
@@ -81,10 +81,6 @@
         closed = true;
     }
 
-    private int bufferLength() {
-        return limit - pos;
-    }
-    
     private int fillBuffer() throws IOException {
         // Compact buffer if needed
         if (pos < limit) {
@@ -108,132 +104,145 @@
         }
     }
     
-    private byte advance() {
+    private int getnext() {
         if (pos < limit) {
             byte b =  encoded[pos];
             pos++;
-            return b;
+            return b & 0xFF;
         } else {
             return -1;
         }
     }
     
-    private byte peek(int i) {
+    private int peek(int i) {
         if (pos + i < limit) {
-            return encoded[pos + i];
+            return encoded[pos + i] & 0xFF;
         } else {
             return -1;
         }
     }
     
-    private void enqueueData() {
-        for (int i = pos; i < limit; i++) {
-            byte b = encoded[i];
-            if (b == LF || b == EQ) {
-                break;
+    private int transfer(
+            final int b, final byte[] buffer, final int from, final int to, boolean keepblanks) {
+        int index = from;
+        if (keepblanks && blanks.length() > 0) {
+            int chunk = Math.min(blanks.length(), to - index);
+            System.arraycopy(blanks.buffer(), 0, buffer, index, chunk);
+            index += chunk;
+            int remaining = blanks.length() - chunk;
+            if (remaining > 0) {
+                decodedBuf.append(blanks.buffer(), chunk, remaining);
             }
-            if (Character.isWhitespace(b)) {
-                blanks.append(b);
+            blanks.clear();
+        }
+        if (b != -1) {
+            if (index < to) {
+                buffer[index++] = (byte) b;
             } else {
-                if (blanks.length() > 0) {
-                    decodedBuf.append(blanks.buffer(), 0, blanks.length());
-                    blanks.clear();
-                }
                 decodedBuf.append(b);
             }
-            pos++;
         }
-    }    
+        return index;
+    }
     
-    private void decode() throws IOException {
-        boolean endOfStream = false;
-        while (decodedBuf.length() == 0) {
+    private int read0(final byte[] buffer, final int off, final int len) throws IOException {
+        boolean eof = false;
+        int from = off;
+        int to = off + len;
+        int index = off;
+
+        // check if a previous invocation left decoded content
+        if (decodedBuf.length() > 0) {
+            int chunk = Math.min(decodedBuf.length(), to - index);
+            System.arraycopy(decodedBuf.buffer(), 0, buffer, index, chunk);
+            decodedBuf.remove(0, chunk);
+            index += chunk;
+        }
+        
+        while (index < to) {
 
-            if (bufferLength() < 3) {
+            if (limit - pos < 3) {
                 int bytesRead = fillBuffer();
-                endOfStream = bytesRead == -1;
+                eof = bytesRead == -1;
             }
-            // end of stream?
-            if (bufferLength() == 0 && endOfStream) {
-                break;
-            }
-            
-            // copy plain bytes until a delimiter is encountered
-            enqueueData();            
             
-            int len = bufferLength();
-            if (len > 0) {
-                // found a delimiter of some kind
-                if (len >= 3 || endOfStream) {
-                    decodeSpecialSequence();
-                }
+            // end of stream?
+            if (limit - pos == 0 && eof) {
+                return index == from ? -1 : index - from;
             }
-        }
-    }
 
-    private void decodeSpecialSequence() throws IOException {
-        byte b1 = advance();
-        if (b1 == LF) {
-            // at end of line
-            if (blanks.length() == 0) {
-                decodedBuf.append((byte) LF);
-            } else {
-                if (blanks.byteAt(0) != EQ) {
-                    // hard line break
-                    decodedBuf.append((byte) CR);
-                    decodedBuf.append((byte) LF);
-                }
-            }
-            blanks.clear();
-        } else if (b1 == EQ) {
-            // found special char '='
-            if (blanks.length() > 0) {
-                decodedBuf.append(blanks.buffer(), 0, blanks.length());
-                blanks.clear();
-            }
-            byte b2 = advance();
-            if (b2 == EQ) {
-                decodedBuf.append(b2);
-                // deal with '==\r\n' brokenness
-                byte bb1 = peek(0);
-                byte bb2 = peek(1);
-                if (bb1 == LF || (bb1 == CR && bb2 == LF)) {
-                    blanks.append(b2);
-                }
-            } else if (Character.isWhitespace((char) b2)) {
-                // soft line break
-                if (b2 != LF) {
-                    blanks.append(b1);
-                    blanks.append(b2);
-                }
-            } else {
-                byte b3 = advance();
-                int upper = convert(b2);
-                int lower = convert(b3);
-                if (upper < 0 || lower < 0) {
-                    if (strict) {
-                        throw new IOException("Malformed encoded value encountered");
+            while (pos < limit && index < to) {
+                int b = encoded[pos++] & 0xFF;
+
+                if (b == LF) {
+                    // at end of line
+                    if (blanks.length() == 0) {
+                        index = transfer(LF, buffer, index, to, false);
+                    } else {
+                        if (blanks.byteAt(0) != EQ) {
+                            // hard line break
+                            index = transfer(CR, buffer, index, to, false);
+                            index = transfer(LF, buffer, index, to, false);
+                        }
+                    }
+                    blanks.clear();
+                } else if (b == EQ) {
+                    if (limit - pos < 2 && !eof) {
+                        // not enough buffered data
+                        pos--;
+                        break;
+                    }
+
+                    // found special char '='
+                    int b2 = getnext();
+                    if (b2 == EQ) {
+                        index = transfer(b2, buffer, index, to, true);
+                        // deal with '==\r\n' brokenness
+                        int bb1 = peek(0);
+                        int bb2 = peek(1);
+                        if (bb1 == LF || (bb1 == CR && bb2 == LF)) {
+                            blanks.append(b2);
+                        }
+                    } else if (Character.isWhitespace((char) b2)) {
+                        // soft line break
+                        index = transfer(-1, buffer, index, to, true);
+                        if (b2 != LF) {
+                            blanks.append(b);
+                            blanks.append(b2);
+                        }
                     } else {
-                        log.warn("Malformed encoded value encountered");
-                        decodedBuf.append((byte) EQ);
-                        if (b2 != -1) decodedBuf.append((byte) b2);
-                        if (b3 != -1) decodedBuf.append((byte) b3);
+                        int b3 = getnext();
+                        int upper = convert(b2);
+                        int lower = convert(b3);
+                        if (upper < 0 || lower < 0) {
+                            if (strict) {
+                                throw new IOException("Malformed encoded value encountered");
+                            } else {
+                                log.warn("Malformed encoded value encountered");
+                                index = transfer(EQ, buffer, index, to, true);
+                                index = transfer(b2, buffer, index, to, false);
+                                index = transfer(b3, buffer, index, to, false);
+                            }
+                        } else {
+                            index = transfer((upper << 4) | lower, buffer, index, to, true);
+                        }
                     }
+                } else if (Character.isWhitespace(b)) {
+                    blanks.append(b);
                 } else {
-                    decodedBuf.append((byte)((upper << 4) | lower));
+                    index = transfer((int) b & 0xFF, buffer, index, to, true);
                 }
             }
-        } else {
-            throw new IllegalStateException();
         }
+        return to - from;
     }
-    
+
     /**
      * Converts '0' => 0, 'A' => 10, etc.
      * @param c ASCII character value.
      * @return Numeric value of hexadecimal character.
      */
-    private int convert(byte c) {
+    private int convert(int c) {
         if (c >= '0' && c <= '9') {
             return (c - '0');
         } else if (c >= 'A' && c <= 'F') {
@@ -266,17 +275,7 @@
         if (closed) {
             throw new IOException("Stream has been closed");
         }
-        decode();
-        if (decodedBuf.length() == 0) {
-            return -1;
-        } else {
-            int chunk = Math.min(decodedBuf.length(), len);
-            if (chunk > 0) {
-                System.arraycopy(decodedBuf.buffer(), 0, b, off, chunk);
-                decodedBuf.remove(0, chunk);
-            }
-            return chunk;
-        }
+        return read0(b, off, len);
     }
 
 }