Skip to content

Commit 6bae80a

Browse files
committed
Different approach for conditional reading
1 parent c2bdfcd commit 6bae80a

1 file changed

Lines changed: 13 additions & 15 deletions

File tree

dissect/cstruct/lexer.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,15 @@ def _emit(self, type: TokenType, value: str, line: int, column: int = 0) -> None
222222
"""Emit a token with the given type and value at the specified line and column."""
223223
self._tokens.append(Token(type, value, line, column))
224224

225-
def _read_conditional(self, condition: Callable[[str], bool], *, or_eof: bool = True) -> str:
226-
"""Read until the current character matches the condition.
225+
def _read_conditional(
226+
self, condition: str | Callable[[str], bool], *, or_eof: bool = True, invert: bool = False
227+
) -> str:
228+
"""Read while or until the current character matches the condition.
227229
228230
Args:
229231
condition: A function that returns ``True`` to stop.
230232
or_eof: If True, also stop if EOF is reached. If False, EOF will not stop the read and will raise an error.
233+
invert: If True, invert the condition (i.e. read while it matches instead of until it matches).
231234
"""
232235
start = self._pos
233236
while True:
@@ -236,8 +239,13 @@ def _read_conditional(self, condition: Callable[[str], bool], *, or_eof: bool =
236239
self._assert_not_eof()
237240
break
238241

239-
if condition(self.data[self._pos]):
240-
break
242+
ch = self.data[self._pos]
243+
if isinstance(condition, str):
244+
if (ch in condition) != invert:
245+
break
246+
else:
247+
if condition(ch) != invert:
248+
break
241249

242250
self._pos += 1
243251

@@ -252,9 +260,6 @@ def _read_until(self, condition: str | Callable[[str], bool], *, or_eof: bool =
252260
condition: Characters to match, or a function that returns ``True`` to stop.
253261
or_eof: If True, also stop if EOF is reached. If False, EOF will not stop the read and will raise an error.
254262
"""
255-
if isinstance(condition, str):
256-
condition = functools.partial(operator.contains, condition)
257-
258263
return self._read_conditional(condition, or_eof=or_eof)
259264

260265
def _read_while(self, condition: str | Callable[[str], bool], *, or_eof: bool = True) -> str:
@@ -264,14 +269,7 @@ def _read_while(self, condition: str | Callable[[str], bool], *, or_eof: bool =
264269
condition: Characters to match, or a function that returns ``True`` to continue.
265270
or_eof: If True, also stop if EOF is reached. If False, EOF will not stop the read and will raise an error.
266271
"""
267-
268-
def _invert(condition: Callable[[str], bool], ch: str) -> bool:
269-
return not condition(ch)
270-
271-
if isinstance(condition, str):
272-
condition = functools.partial(operator.contains, condition)
273-
274-
return self._read_conditional(functools.partial(_invert, condition), or_eof=or_eof)
272+
return self._read_conditional(condition, or_eof=or_eof, invert=True)
275273

276274
def _skip_whitespace(self) -> None:
277275
"""Skip whitespace characters."""

0 commit comments

Comments
 (0)