root / pkpgcounter / trunk / pkpgpdls / spl1.py @ 555

Revision 555, 4.9 kB (checked in by jerome, 16 years ago)

Each parser now has a 'format' attribute containing its short name.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[408]1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3#
4# pkpgcounter : a generic Page Description Language parser
5#
[443]6# (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet <alet@librelogiciel.com>
[463]7# This program is free software: you can redistribute it and/or modify
[408]8# it under the terms of the GNU General Public License as published by
[463]9# the Free Software Foundation, either version 3 of the License, or
[408]10# (at your option) any later version.
[463]11#
[408]12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
[463]18# along with this program.  If not, see <http://www.gnu.org/licenses/>.
[408]19#
20# $Id$
21#
22
23"""This modules implements a page counter for SPL1 documents."""
24
25import os
26import mmap
[533]27import struct
[408]28
29import pdlparser
[410]30import version
[408]31
32ESCAPECHARS = (chr(0x1b), chr(0x24))
33
34class Parser(pdlparser.PDLParser) :
35    """A parser for SPL1 documents."""
[555]36    format = "SPL1 (aka GDI)"
[408]37    def isValid(self) :   
[487]38        """Returns True if data is SPL1, else False."""
[522]39        if ((self.firstblock[:128].find("\033%-12345X") != -1) and \
40            (self.firstblock.find("$PJL ") != -1) and \
41             ((self.firstblock.find("LANGUAGE=SMART") != -1) or \
42              (self.firstblock.find("LANGUAGE = SMART") != -1))) :
[408]43            return True
44        else :   
45            return False
46           
47    def littleEndian(self) :
48        """Toggles to little endianness."""
49        self.unpackType = { 1 : "B", 2 : "<H", 4 : "<I" }
50        self.unpackShort = self.unpackType[2]
51        self.unpackLong = self.unpackType[4]
[533]52        # self.logdebug("Little Endian")
[408]53        return 0
54       
55    def bigEndian(self) :
56        """Toggles to big endianness."""
57        self.unpackType = { 1 : "B", 2 : ">H", 4 : ">I" }
58        self.unpackShort = self.unpackType[2]
59        self.unpackLong = self.unpackType[4]
[533]60        # self.logdebug("Big Endian")
[408]61        return 0
62   
63    def escape(self, nextpos) :   
64        """Handles the ESC code."""
[409]65        self.isbitmap = False
[408]66        pos = endpos = nextpos
67        minfile = self.minfile
68        if minfile[pos : pos+8] == r"%-12345X" :
69            endpos = pos + 9
70        elif minfile[pos-1] in ESCAPECHARS :   
71            endpos = pos
72        else :   
73            return 0
74        endmark = (chr(0x1b), chr(0x00))
75        asciilimit = chr(0x80)
76        quotes = 0
77        while (minfile[endpos] not in endmark) and \
78               ((minfile[endpos] < asciilimit) or (quotes % 2)) :
79            if minfile[endpos] == '"' :
80                quotes += 1
81            endpos += 1
82           
83        # Store this in a per page mapping.   
84        # NB : First time will be at page 0 (i.e. **before** page 1) !
85        stuff = self.escapedStuff.setdefault(self.pagecount, [])
[409]86        datas = minfile[pos-1 : endpos]
87        stuff.append(datas)
88        if datas.endswith("$PJL BITMAP START\r\n") :
89            self.isbitmap = True
[533]90            # self.logdebug("New bitmap")
[409]91        self.logdebug("Escaped datas : [%s]" % repr(datas))
[408]92        return endpos - pos + 1
93       
94    def getJobSize(self) :
95        """Counts pages in an SPL1 document.
96       
97           Algorithm by Jerome Alet.
98        """
99        infileno = self.infile.fileno()
[409]100        self.minfile = minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED)
[408]101        self.pagecount = 0
102        self.escapedStuff = {}   # For escaped datas, mostly PJL commands
103        self.bigEndian()
[409]104        self.isbitmap = False
[408]105        pos = 0
[533]106        unpack = struct.unpack
[408]107        try :
108            try :
109                while 1 :
[409]110                    tag = minfile[pos]
[408]111                    if tag in ESCAPECHARS :
112                        pos += self.escape(pos+1)
113                    else :   
[409]114                        if not self.isbitmap :
[410]115                            raise pdlparser.PDLParserError, "Unfortunately SPL1 is incompletely recognized. Parsing aborted. Please report the problem to %s" % version.__authoremail__
[533]116                        (offset,
117                         seqnum) = unpack(">IH", minfile[pos:pos+6])
118                        # self.logdebug("Offset : %i      Sequence Number : %i" % (offset, seqnum))
119                        if not seqnum : 
120                            # Sequence number resets to 0 for each new page.
[409]121                            self.pagecount += 1
[408]122                        pos += 4 + offset
[533]123            except struct.error, msg :     
124                raise pdlparser.PDLParserError, "Unfortunately SPL1 is incompletely recognized (%s). Parsing aborted. Please report the problem to %s" % (msg, version.__authoremail__)
[408]125            except IndexError : # EOF ?           
126                pass
127        finally :
[409]128            minfile.close()
[408]129        return self.pagecount
Note: See TracBrowser for help on using the browser.