Changeset 1487

Show
Ignore:
Timestamp:
05/21/04 22:40:08 (20 years ago)
Author:
jalet
Message:

All the code for pkpgcounter is now in pdlanalyzer.py

Location:
pykota/trunk
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/pkpgcounter

    r1482 r1487  
    2424# 
    2525# $Log$ 
     26# Revision 1.11  2004/05/21 20:40:07  jalet 
     27# All the code for pkpgcounter is now in pdlanalyzer.py 
     28# 
    2629# Revision 1.10  2004/05/18 09:59:54  jalet 
    2730# pkpgcounter is now just a wrapper around the PDLAnalyzer class 
     
    5861# 
    5962 
    60 import sys 
    6163from pykota import pdlanalyzer 
    6264     
    6365if __name__ == "__main__" :     
    64     if (len(sys.argv) < 2) or ((not sys.stdin.isatty()) and ("-" not in sys.argv[1:])) : 
    65         sys.argv.append("-") 
    66          
    67     totalsize = 0     
    68     for arg in sys.argv[1:] : 
    69         try : 
    70             parser = pdlanalyzer.PDLAnalyzer(arg) 
    71             totalsize += parser.getJobSize() 
    72         except TypeError, msg :     
    73             sys.stderr.write("%s\n" % msg) 
    74             sys.stderr.flush() 
    75     print "%s" % totalsize 
     66    pdlanalyzer.main() 
  • pykota/trunk/NEWS

    r1485 r1487  
    2424    - 1.19alpha10 : 
    2525     
     26        - Improvements to generic PDL Analyzer. 
     27         
    2628        - 25% Speedup in PCL parser. Getting more of the Python version 
    2729          will probably be difficult, since the completely table driven  
  • pykota/trunk/pykota/pdlanalyzer.py

    r1485 r1487  
    2222# 
    2323# $Log$ 
     24# Revision 1.3  2004/05/21 20:40:08  jalet 
     25# All the code for pkpgcounter is now in pdlanalyzer.py 
     26# 
    2427# Revision 1.2  2004/05/19 19:09:36  jalet 
    2528# Speed improvement 
     
    3235 
    3336import sys 
    34 import os 
    3537import struct 
    3638import tempfile 
     39     
     40KILOBYTE = 1024     
     41MEGABYTE = 1024 * KILOBYTE     
     42 
     43class PDLAnalyzerError(Exception): 
     44    """An exception for PDL Analyzer related stuff.""" 
     45    def __init__(self, message = ""): 
     46        self.message = message 
     47        Exception.__init__(self, message) 
     48    def __repr__(self): 
     49        return self.message 
     50    __str__ = __repr__ 
    3751     
    3852class PostScriptAnalyzer : 
     
    4458        """Count pages in a DSC compliant PostScript document.""" 
    4559        pagecount = 0 
    46         pagenum = None 
    4760        while 1 : 
    4861            line = self.infile.readline() 
     
    6376        if newpos >= self.len : 
    6477            oldlen = self.len 
    65             self.data = self.infile.read(1024*1024) 
     78            self.data = self.infile.read(MEGABYTE) 
    6679            self.len = len(self.data) 
    6780            if not self.len : 
     
    7689            char = self.data[self.pos] 
    7790        else :     
    78             self.data = self.infile.read(1024*1024) 
     91            self.data = self.infile.read(MEGABYTE) 
    7992            self.len = len(self.data) 
    8093            self.pos = 0 
     
    182195        # PCL files with this. If resets < 2, then the file is 
    183196        # probably not a valid PCL file, so we return 0 
    184         if not pagecount : 
    185             return copies * (resets - 3) * (resets > 2) 
    186         else : 
    187             return copies * pagecount 
     197        return copies * (pagecount or ((resets - 3) * (resets > 2))) 
    188198         
    189199class PCLXLAnalyzer : 
    190200    def __init__(self, infile) : 
    191201        """Initialize PCLXL Analyzer.""" 
    192         raise TypeError, "PCLXL (aka PCL6) is not supported yet." 
     202        raise PDLAnalyzerError, "PCLXL (aka PCL6) is not supported yet." 
    193203        self.infile = infile 
    194204        self.islittleendian = None 
     
    205215                    self.bigendian() 
    206216        if not found : 
    207             raise TypeError, "This file doesn't seem to be PCLXL (aka PCL6)" 
    208         else :     
    209             self.tags = [None] * 256     
     217            raise PDLAnalyzerError, "This file doesn't seem to be PCLXL (aka PCL6)" 
     218        else :     
     219            self.tags = [lambda: None] * 256     
    210220            self.tags[0x28] = self.bigendian    # big endian 
    211221            self.tags[0x29] = self.littleendian # big endian 
     
    213223            self.tags[0x44] = self.endPage      # EndPage 
    214224             
    215             self.tags[0xc0] = 1 # ubyte 
    216             self.tags[0xc1] = 2 # uint16 
    217             self.tags[0xc2] = 4 # uint32 
    218             self.tags[0xc3] = 2 # sint16 
    219             self.tags[0xc4] = 4 # sint32 
    220             self.tags[0xc5] = 4 # real32 
     225            self.tags[0xc0] = lambda: 1 # ubyte 
     226            self.tags[0xc1] = lambda: 2 # uint16 
     227            self.tags[0xc2] = lambda: 4 # uint32 
     228            self.tags[0xc3] = lambda: 2 # sint16 
     229            self.tags[0xc4] = lambda: 4 # sint32 
     230            self.tags[0xc5] = lambda: 4 # real32 
    221231             
    222232            self.tags[0xc8] = self.array_8  # ubyte_array 
     
    227237            self.tags[0xcd] = self.array_32 # real32_array 
    228238             
    229             self.tags[0xd0] = 2 # ubyte_xy 
    230             self.tags[0xd1] = 4 # uint16_xy 
    231             self.tags[0xd2] = 8 # uint32_xy 
    232             self.tags[0xd3] = 4 # sint16_xy 
    233             self.tags[0xd4] = 8 # sint32_xy 
    234             self.tags[0xd5] = 8 # real32_xy 
    235              
    236             self.tags[0xd0] = 4  # ubyte_box 
    237             self.tags[0xd1] = 8  # uint16_box 
    238             self.tags[0xd2] = 16 # uint32_box 
    239             self.tags[0xd3] = 8  # sint16_box 
    240             self.tags[0xd4] = 16 # sint32_box 
    241             self.tags[0xd5] = 16 # real32_box 
    242              
    243             self.tags[0xf8] = 1 # attr_ubyte 
    244             self.tags[0xf9] = 2 # attr_uint16 
     239            self.tags[0xd0] = lambda: 2 # ubyte_xy 
     240            self.tags[0xd1] = lambda: 4 # uint16_xy 
     241            self.tags[0xd2] = lambda: 8 # uint32_xy 
     242            self.tags[0xd3] = lambda: 4 # sint16_xy 
     243            self.tags[0xd4] = lambda: 8 # sint32_xy 
     244            self.tags[0xd5] = lambda: 8 # real32_xy 
     245             
     246            self.tags[0xd0] = lambda: 4  # ubyte_box 
     247            self.tags[0xd1] = lambda: 8  # uint16_box 
     248            self.tags[0xd2] = lambda: 16 # uint32_box 
     249            self.tags[0xd3] = lambda: 8  # sint16_box 
     250            self.tags[0xd4] = lambda: 16 # sint32_box 
     251            self.tags[0xd5] = lambda: 16 # real32_box 
     252             
     253            self.tags[0xf8] = lambda: 1 # attr_ubyte 
     254            self.tags[0xf9] = lambda: 2 # attr_uint16 
    245255             
    246256            self.tags[0xfa] = self.embeddedData      # dataLength 
     
    263273    def handleArray(self, itemsize) :         
    264274        """Handles arrays.""" 
     275        pos = self.infile.tell() 
    265276        datatype = self.infile.read(1) 
    266         length = self.tags[ord(datatype)] 
    267         sarraysize = self.infile.read(length) 
    268         if self.islittleendian : 
    269             fmt = "<" 
    270         else :     
    271             fmt = ">" 
    272         if length == 1 :     
    273             fmt += "B" 
    274         elif length == 2 :     
    275             fmt += "H" 
    276         elif length == 4 :     
    277             fmt += "I" 
    278         else :     
    279             raise TypeError, "Error on array size at %s" % self.infile.tell() 
    280         arraysize = struct.unpack(fmt, sarraysize)[0] 
    281         return arraysize * itemsize 
     277        length = self.tags[ord(datatype)]() 
     278        if length is None : 
     279            self.debug("Bogus array length at %s" % pos) 
     280        else :     
     281            sarraysize = self.infile.read(length) 
     282            if self.islittleendian : 
     283                fmt = "<" 
     284            else :     
     285                fmt = ">" 
     286            if length == 1 :     
     287                fmt += "B" 
     288            elif length == 2 :     
     289                fmt += "H" 
     290            elif length == 4 :     
     291                fmt += "I" 
     292            else :     
     293                raise PDLAnalyzerError, "Error on array size at %s" % self.infile.tell() 
     294            arraysize = struct.unpack(fmt, sarraysize)[0] 
     295            self.debug("Array at %s, itemsize %s, datatype 0x%02x, size %s" % (pos, itemsize, ord(datatype), arraysize)) 
     296            return arraysize * itemsize 
    282297         
    283298    def array_8(self) :     
     
    295310    def embeddedDataSmall(self) : 
    296311        """Handle small amounts of data.""" 
    297         return ord(self.infile.read(1)) 
     312        pos = self.infile.tell() 
     313        val = ord(self.infile.read(1)) 
     314        self.debug("smalldatablock at %s (0x%02x)" % (pos, val)) 
     315        return val 
    298316         
    299317    def embeddedData(self) : 
     
    303321        else :     
    304322            fmt = ">I" 
    305         return struct.unpack(fmt, self.infile.read(4))[0] 
     323        pos = self.infile.tell() 
     324        val = struct.unpack(fmt, self.infile.read(4))[0] 
     325        self.debug("datablock at %s (0x%08x)" % (pos, val)) 
     326        return val 
    306327         
    307328    def littleendian(self) :         
     
    317338        self.pagecount = 0 
    318339        while 1 : 
    319             pos = self.infile.tell() 
    320340            char = self.infile.read(1) 
    321341            if not char : 
    322342                break 
    323343            index = ord(char)     
    324             length = self.tags[index] 
    325             if length is not None : 
    326                 if not length : 
    327                     self.debug("Unrecognized tag 0x%02x at %s\n" % (index, self.infile.tell())) 
    328                 elif callable(length) :     
    329                     length = length() 
    330                 if length :     
    331                     self.infile.read(length)     
     344            length = self.tags[index]() 
     345            if length :     
     346                self.infile.read(length)     
    332347        return self.pagecount 
    333      
     348         
    334349class PDLAnalyzer :     
    335350    """Generic PDL Analyzer class.""" 
    336351    def __init__(self, filename) : 
    337         """Initializes the PDL analyzer.""" 
     352        """Initializes the PDL analyzer. 
     353         
     354           filename is the name of the file or '-' for stdin. 
     355           filename can also be a file-like object which  
     356           supports read() and seek(). 
     357        """ 
    338358        self.filename = filename 
    339359         
     
    341361        """Returns the job's size.""" 
    342362        self.openFile() 
    343         pdlhandler = self.detectPDLHandler() 
    344         if pdlhandler is not None : 
     363        try : 
     364            pdlhandler = self.detectPDLHandler() 
     365        except PDLAnalyzerError, msg :     
     366            self.closeFile() 
     367            raise PDLAnalyzerError, "ERROR : Unknown file format for %s (%s)" % (self.filename, msg) 
     368        else : 
    345369            try : 
    346370                size = pdlhandler(self.infile).getJobSize() 
     
    348372                self.closeFile() 
    349373            return size 
    350         else :         
    351             self.closeFile() 
    352             raise TypeError, "ERROR : Unknown file format for %s" % self.filename 
    353374         
    354375    def openFile(self) :     
    355376        """Opens the job's data stream for reading.""" 
    356         if self.filename == "-" : 
     377        self.mustclose = 1 
     378        if hasattr(self.filename, "read") and hasattr(self.filename, "seek") : 
     379            # filename is in fact a file-like object  
     380            self.infile = self.filename 
     381            self.mustclose = 0  # we don't want to close this file when finished 
     382        elif self.filename == "-" : 
    357383            # we must read from stdin 
    358384            # but since stdin is not seekable, we have to use a temporary 
     
    360386            self.infile = tempfile.TemporaryFile() 
    361387            while 1 : 
    362                 data = sys.stdin.read(256 * 1024)  
     388                data = sys.stdin.read(MEGABYTE)  
    363389                if not data : 
    364390                    break 
     
    371397             
    372398    def closeFile(self) :         
    373         """Closes the job's data stream.""" 
    374         self.infile.close()     
     399        """Closes the job's data stream if we can close it.""" 
     400        if self.mustclose : 
     401            self.infile.close()     
    375402         
    376403    def isPostScript(self, data) :     
     
    415442        # Try to detect file type by reading first block of datas     
    416443        self.infile.seek(0) 
    417         firstblock = self.infile.read(1024) 
     444        firstblock = self.infile.read(KILOBYTE) 
    418445        self.infile.seek(0) 
    419446        if self.isPostScript(firstblock) : 
     
    423450        elif self.isPCL(firstblock) :     
    424451            return PCLAnalyzer 
     452        else :     
     453            raise PDLAnalyzerError, "Analysis of first data block failed." 
     454             
     455def main() :     
     456    """Entry point for PDL Analyzer.""" 
     457    if (len(sys.argv) < 2) or ((not sys.stdin.isatty()) and ("-" not in sys.argv[1:])) : 
     458        sys.argv.append("-") 
     459         
     460    totalsize = 0     
     461    for arg in sys.argv[1:] : 
     462        try : 
     463            parser = PDLAnalyzer(arg) 
     464            totalsize += parser.getJobSize() 
     465        except PDLAnalyzerError, msg :     
     466            sys.stderr.write("%s\n" % msg) 
     467            sys.stderr.flush() 
     468    print "%s" % totalsize 
     469     
     470if __name__ == "__main__" :     
     471    main()