You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ju...@apache.org on 2010/01/15 00:52:00 UTC

svn commit: r899479 - /pdfbox/trunk/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java

Author: jukka
Date: Thu Jan 14 23:52:00 2010
New Revision: 899479

URL: http://svn.apache.org/viewvc?rev=899479&view=rev
Log:
PDFBOX-591: PDFBox performance issue: BaseParser.readUntilEndStream() rewrite

Patch by Mel Martinez, with minor improvements by me

Modified:
    pdfbox/trunk/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java

Modified: pdfbox/trunk/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java?rev=899479&r1=899478&r2=899479&view=diff
==============================================================================
--- pdfbox/trunk/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java (original)
+++ pdfbox/trunk/src/main/java/org/apache/pdfbox/pdfparser/BaseParser.java Thu Jan 14 23:52:00 2010
@@ -57,17 +57,33 @@
      */
     private static final Log log = LogFactory.getLog(BaseParser.class);
 
+    private static final int E = 'e';
+    private static final int N = 'n';
+    private static final int D = 'd';
+
+    private static final int S = 's';
+    private static final int T = 't';
+    private static final int R = 'r';
+    //private static final int E = 'e';
+    private static final int A = 'a';
+    private static final int M = 'm';
+
+    private static final int O = 'o';
+    private static final int B = 'b';
+    private static final int J = 'j';
+
     /**
      * This is a byte array that will be used for comparisons.
      */
     public static final byte[] ENDSTREAM =
-        new byte[] {101,110,100,115,116,114,101,97,109};//"endstream".getBytes( "ISO-8859-1" );
+        new byte[] { E, N, D, S, T, R, E, A, M };
 
     /**
      * This is a byte array that will be used for comparisons.
      */
     public static final byte[] ENDOBJ =
-        new byte[] {101,110,100,111,98,106};//"endobj".getBytes( "ISO-8859-1" );
+        new byte[] { E, N, D, O, B, J };
+
     /**
      * This is a byte array that will be used for comparisons.
      */
@@ -375,6 +391,7 @@
         }
         return stream;
     }
+
     /**
      * This method will read through the current stream object until
      * we find the keyword "endstream" meaning we're at the end of this
@@ -383,69 +400,72 @@
      * this case as well.
      * @param out The stream we write out to. 
      * @throws IOException
-     */
-    private void readUntilEndStream( OutputStream out ) throws IOException
-    {
-        int byteRead = 0;
-        byte[] buffer = new byte[ENDSTREAM.length];
-        int nextIdx = pdfSource.read(buffer) % buffer.length; 
-        if (nextIdx == -1)
-        { 
-            return;
-        }
-        while(byteRead != -1 ) 
-        {
-            if (cmpCircularBuffer( buffer, (nextIdx-ENDSTREAM.length + buffer.length)%buffer.length, ENDSTREAM )) 
-            {
-                pdfSource.unread( ENDSTREAM );
-                return;
-            }
-            /*
-             * occasionally steam objects do not write the endstream tag and just terminate
-             * the object with an endobj tag so we want to stop there as well. 
-             */
-            int endObjStart = (nextIdx-ENDOBJ.length+ buffer.length)%buffer.length;
-            if (cmpCircularBuffer( buffer, endObjStart, ENDOBJ )) 
-            {
-                // data is written to out only when it is going to be overwritten.
-                // write out the rest of the data in the buffer since ENDOBJ is smaller then the buffer
-                for (int i = nextIdx; i < buffer.length && i < endObjStart; i++ ) 
-                {
-                    out.write(buffer[i]);
-                }
-                pdfSource.unread( ENDOBJ );
-                return;
-            }
-
-            out.write( buffer[nextIdx] );
-
+     */    
+    private void readUntilEndStream( OutputStream out ) throws IOException{
+        int byteRead;
+        do{ //use a fail fast test for end of stream markers
             byteRead = pdfSource.read();
-            buffer[nextIdx] = (byte)byteRead;
-
-            if (++nextIdx == buffer.length) 
-            {
-                nextIdx = 0;
+            if(byteRead==E){//only branch if "e"
+                byteRead = pdfSource.read();
+                if(byteRead==N){ //only continue branch if "en"
+                    byteRead = pdfSource.read();
+                    if(byteRead==D){//up to "end" now
+                        byteRead = pdfSource.read();
+                        if(byteRead==S){
+                            byteRead = pdfSource.read();
+                            if(byteRead==T){
+                                byteRead = pdfSource.read();
+                                if(byteRead==R){
+                                    byteRead = pdfSource.read();
+                                    if(byteRead==E){
+                                        byteRead = pdfSource.read();
+                                        if(byteRead==A){
+                                            byteRead = pdfSource.read();
+                                            if(byteRead==M){
+                                                //found the whole marker
+                                                pdfSource.unread( ENDSTREAM );
+                                                return;
+                                            }
+                                        }else{
+                                            out.write(ENDSTREAM, 0, 7);
+                                        }
+                                    }else{
+                                        out.write(ENDSTREAM, 0, 6);
+                                    }
+                                }else{
+                                    out.write(ENDSTREAM, 0, 5);
+                                }
+                            }else{
+                                out.write(ENDSTREAM, 0, 4);
+                            }
+                        }else if(byteRead==O){
+                            byteRead = pdfSource.read();
+                            if(byteRead==B){
+                                byteRead = pdfSource.read();
+                                if(byteRead==J){
+                                    //found whole marker
+                                    pdfSource.unread( ENDOBJ );
+                                    return;
+                                }
+                            }else{
+                                out.write(ENDOBJ, 0, 4);
+                            }
+                        }else{
+                            out.write(E);
+                            out.write(N);
+                            out.write(D);
+                        }
+                    }else{
+                        out.write(E);
+                        out.write(N);
+                    }
+                }else{
+                    out.write(E);
+                }
             }
-        }   
-    }
+            if(byteRead!=-1)out.write(byteRead);
 
-    /**
-     * This basically checks to see if the next compareTo.length bytes of the
-     * buffer match the compareTo byte array.
-     * @param buffer Circular buffer to look for string in
-     * @param currentIndex Index in buffer to start comparison from
-     * @param compareTo String to find in circular buffer at index
-     */
-    private boolean cmpCircularBuffer( byte[] buffer, int currentIndex, byte[] compareTo )
-    {
-        int cmpLen = compareTo.length;
-        int buflen = buffer.length;
-        boolean match = true;
-        for( int i=0; match && i<cmpLen; ++i ) 
-        {
-            match = buffer[(currentIndex+i)%buflen] == compareTo[i];
-        }
-        return match;
+        }while(byteRead!=-1);
     }
 
     /**