1 # -*- encoding: utf-8 -*-
4 # Copyright (C) 2007-2011 Jörg Lehmann <joergl@users.sourceforge.net>
5 # Copyright (C) 2007-2011 André Wobst <wobsta@users.sourceforge.net>
7 # This file is part of PyX (http://pyx.sourceforge.net/).
9 # PyX is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
14 # PyX is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with PyX; if not, write to the Free Software
21 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29 def __init__(self
, filename
):
30 self
.file = open(filename
, "rb")
36 return self
.file.tell()
39 return self
.file.eof()
41 def read(self
, bytes
):
42 return self
.file.read(bytes
)
44 def readint(self
, bytes
=4, signed
=0):
48 value
= ord(self
.file.read(1))
49 if first
and signed
and value
> 127:
52 result
= 256 * result
+ value
57 return struct
.unpack(">l", self
.file.read(4))[0]
60 return struct
.unpack(">L", self
.file.read(4))[0]
64 return struct
.unpack(">l", "\0"+self
.file.read(3))[0]
68 return struct
.unpack(">L", "\0"+self
.file.read(3))[0]
71 return struct
.unpack(">h", self
.file.read(2))[0]
74 return struct
.unpack(">H", self
.file.read(2))[0]
77 return struct
.unpack("b", self
.file.read(1))[0]
80 return struct
.unpack("B", self
.file.read(1))[0]
82 def readstring(self
, bytes
):
84 assert l
<= bytes
-1, "inconsistency in file: string too long"
85 return self
.file.read(bytes
-1)[:l
]
89 class stringreader(reader
):
91 def __init__(self
, s
):
92 self
.file = io
.StringIO(s
)
96 """cursor to read a string token by token"""
98 def __init__(self
, data
, startstring
=None, eattokensep
=1, tokenseps
=" \t\r\n", tokenstarts
="()<>[]{}/%"):
99 """creates a cursor for the string data
101 startstring is a string at which the cursor should start at. The first
102 ocurance of startstring is used. When startstring is not in data, an
103 exception is raised, otherwise the cursor is set to the position right
104 after the startstring. When eattokenseps is set, startstring must be
105 followed by a tokensep and this first tokensep is also consumed.
106 tokenseps is a string containing characters to be used as token
107 separators. tokenstarts is a string containing characters which
108 directly (even without intermediate token separator) start a new token.
111 if startstring
is not None:
112 self
.pos
= self
.data
.index(startstring
) + len(startstring
)
115 self
.tokenseps
= tokenseps
116 self
.tokenstarts
= tokenstarts
118 if self
.data
[self
.pos
] not in self
.tokenstarts
:
119 if self
.data
[self
.pos
] not in self
.tokenseps
:
120 raise ValueError("cursor initialization string is not followed by a token separator")
124 """get the next token
126 Leading token separators and comments are silently consumed. The first token
127 separator after the token is also silently consumed."""
128 while self
.data
[self
.pos
] in self
.tokenseps
:
130 # ignore comments including subsequent whitespace characters
131 while self
.data
[self
.pos
] == "%":
132 while self
.data
[self
.pos
] not in "\r\n":
134 while self
.data
[self
.pos
] in self
.tokenseps
:
137 while self
.data
[self
.pos
] not in self
.tokenseps
:
138 # any character in self.tokenstarts ends the token
139 if self
.pos
>startpos
and self
.data
[self
.pos
] in self
.tokenstarts
:
142 result
= self
.data
[startpos
:self
.pos
]
143 if self
.data
[self
.pos
] in self
.tokenseps
:
144 self
.pos
+= 1 # consume a single tokensep
148 """get the next token as an integer"""
149 return int(self
.gettoken())
151 def getbytes(self
, count
):
152 """get the next count bytes"""
155 return self
.data
[startpos
: self
.pos
]