Changeset 561 for pkpgcounter/trunk

Show
Ignore:
Timestamp:
12/28/07 23:58:59 (17 years ago)
Author:
jerome
Message:

Partial rewrite of PostScript? parser to increase both readability and speed (around 25% on my tests)

Location:
pkpgcounter/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • pkpgcounter/trunk/NEWS

    r550 r561  
    2121pkpgcounter News : 
    2222 
     23  * 3.51 : 
     24   
     25    - Partial rewrite of the PostScript parser, with huge performance increase. 
     26     
     27    - Fixed a problem in the PostScript parser where the number of copies set with 
     28      e.g. "dvips -c 9 -o output.ps input.dvi" wasn't correctly detected.  
     29       
    2330  * 3.50 : 
    2431   
  • pkpgcounter/trunk/pkpgpdls/postscript.py

    r560 r561  
    6969        return pagecount * self.copies 
    7070         
     71    def setcopies(self, pagenum, txtvalue) :     
     72        """Tries to extract a number of copies from a textual value and set the instance attributes accordingly.""" 
     73        try : 
     74            number = int(txtvalue) 
     75        except (ValueError, TypeError) :      
     76            pass 
     77        else :     
     78            if number > self.pages[pagenum]["copies"] : 
     79                self.pages[pagenum]["copies"] = number 
     80                 
    7181    def natively(self) : 
    7282        """Count pages in a DSC compliant PostScript document.""" 
     
    8191        for line in self.infile : 
    8292            line = line.strip() 
    83             if (not prescribe) and line.startswith(r"%%BeginResource: procset pdf") \ 
    84                and not acrobatmarker : 
    85                 notrust = True # Let this stuff be managed by GhostScript, but we still extract number of copies 
    86             elif line.startswith(r"%ADOPrintSettings: L") : 
     93            parts = line.split() 
     94            nbparts = len(parts) 
     95            part0 = parts[0] 
     96            if part0 == r"%ADOPrintSettings:" : 
    8797                acrobatmarker = True 
    88             elif line.startswith("!R!") : 
     98            elif part0 == "!R!" :     
    8999                prescribe = True 
    90             elif line.startswith(r"%%Pages: ") : 
     100            elif part0 == r"%%Pages:" : 
    91101                try : 
    92                     pagescomment = max(pagescomment or 0, int(line.split()[1])) 
     102                    pagescomment = max(pagescomment or 0, int(parts[1])) 
    93103                except ValueError : 
    94104                    pass # strange, to say the least 
    95             elif line.startswith(r"%%Page: ") or line.startswith(r"(%%[Page: ") : 
    96                 proceed = 1 
     105            elif (part0 == r"%%BeginNonPPDFeature:") \ 
     106                  and (nbparts > 2) \ 
     107                  and (parts[1] == "NumCopies") : 
     108                self.setcopies(pagecount, parts[2]) 
     109            elif (part0 == r"%%Requirements:") \ 
     110                  and (nbparts > 1) \ 
     111                  and (parts[1] == "numcopies(") : 
     112                try : 
     113                    self.setcopies(pagecount, line.split('(')[1].split(')')[0]) 
     114                except IndexError : 
     115                    pass 
     116            elif part0 == "/#copies" : 
     117                if nbparts > 1 : 
     118                    self.setcopies(pagecount, parts[1]) 
     119            elif part0 == r"%RBINumCopies:" :    
     120                if nbparts > 1 : 
     121                    self.setcopies(pagecount, parts[1]) 
     122            elif (parts[:4] == ["1", "dict", "dup", "/NumCopies"]) \ 
     123                  and (nbparts > 4) : 
     124                # handle # of copies set by mozilla/kprinter 
     125                self.setcopies(pagecount, parts[4]) 
     126            elif (parts[:6] == ["{", "pop", "1", "dict", "dup", "/NumCopies"]) \ 
     127                  and (nbparts > 6) : 
     128                # handle # of copies set by firefox/kprinter/cups (alternate syntax) 
     129                self.setcopies(pagecount, parts[6]) 
     130            elif (part0 == r"%%Page:") or (part0 == r"(%%[Page:") : 
     131                proceed = True 
    97132                try : 
    98133                    # treats both "%%Page: x x" and "%%Page: (x-y) z" (probably N-up mode) 
    99134                    newpagenum = int(line.split(']')[0].split()[-1]) 
    100135                except :     
    101                     notinteger = 1 # It seems that sometimes it's not an integer but an EPS file name 
     136                    notinteger = True # It seems that sometimes it's not an integer but an EPS file name 
    102137                else :     
    103                     notinteger = 0 
     138                    notinteger = False 
    104139                    if newpagenum == oldpagenum : 
    105                         proceed = 0 
     140                        proceed = False 
    106141                    else : 
    107142                        oldpagenum = newpagenum 
     
    109144                    pagecount += 1 
    110145                    self.pages[pagecount] = { "copies" : self.pages[pagecount-1]["copies"] } 
    111             elif line.startswith(r"%%Requirements: numcopies(") :     
    112                 try : 
    113                     number = int(line.split('(')[1].split(')')[0]) 
    114                 except :      
    115                     pass 
    116                 else :     
    117                     if number > self.pages[pagecount]["copies"] : 
    118                         self.pages[pagecount]["copies"] = number 
    119             elif line.startswith(r"%%BeginNonPPDFeature: NumCopies ") : 
    120                 # handle # of copies set by some Windows printer driver 
    121                 try : 
    122                     number = int(line.split()[2]) 
    123                 except :      
    124                     pass 
    125                 else :     
    126                     if number > self.pages[pagecount]["copies"] : 
    127                         self.pages[pagecount]["copies"] = number 
    128             elif line.startswith("1 dict dup /NumCopies ") : 
    129                 # handle # of copies set by mozilla/kprinter 
    130                 try : 
    131                     number = int(line.split()[4]) 
    132                 except :      
    133                     pass 
    134                 else :     
    135                     if number > self.pages[pagecount]["copies"] : 
    136                         self.pages[pagecount]["copies"] = number 
    137             elif line.startswith("{ pop 1 dict dup /NumCopies ") : 
    138                 # handle # of copies set by firefox/kprinter/cups (alternate syntax) 
    139                 try : 
    140                     number = int(line.split()[6]) 
    141                 except : 
    142                     pass 
    143                 else : 
    144                     if number > self.pages[pagecount]["copies"] : 
    145                         self.pages[pagecount]["copies"] = number 
     146            elif (not prescribe) \ 
     147               and (parts[:3] == [r"%%BeginResource:", "procset", "pdf"]) \ 
     148               and not acrobatmarker : 
     149                notrust = True # Let this stuff be managed by GhostScript, but we still extract number of copies 
    146150            elif line.startswith("/languagelevel where{pop languagelevel}{1}ifelse 2 ge{1 dict dup/NumCopies") : 
    147                 try : 
    148                     number = int(previousline[2:]) 
    149                 except : 
    150                     pass 
    151                 else : 
    152                     if number > self.pages[pagecount]["copies"] : 
    153                         self.pages[pagecount]["copies"] = number 
    154             elif line.startswith("/#copies ") : 
    155                 try : 
    156                     number = int(line.split()[1]) 
    157                 except :      
    158                     pass 
    159                 else :     
    160                     if number > self.pages[pagecount]["copies"] : 
    161                         self.pages[pagecount]["copies"] = number 
    162             elif line.startswith(r"%RBINumCopies: ") :    
    163                 try : 
    164                     number = int(line.split()[1]) 
    165                 except :      
    166                     pass 
    167                 else :     
    168                     if number > self.pages[pagecount]["copies"] : 
    169                         self.pages[pagecount]["copies"] = number 
    170             else :    
    171                 parts = line.split() 
    172                 if (len(parts) > 1) and (parts[1] == "@copies") : 
    173                     try : 
    174                         number = int(parts[0]) 
    175                     except :      
    176                         pass 
    177                     else :     
    178                         if number > self.pages[pagecount]["copies"] : 
    179                             self.pages[pagecount]["copies"] = number 
     151                self.setcopies(pagecount, previousline[2:]) 
     152            elif (nbparts > 1) and (parts[1] == "@copies") : 
     153                self.setcopies(pagecount, part0) 
    180154            previousline = line 
    181155