Skip to content

Commit 89736f3

Browse files
committed
Merge _read_while and _read_until
1 parent c0f5a4b commit 89736f3

1 file changed

Lines changed: 23 additions & 26 deletions

File tree

dissect/cstruct/lexer.py

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from __future__ import annotations
22

33
import enum
4+
import functools
5+
import operator
46
import re
57
from typing import TYPE_CHECKING
68

@@ -220,11 +222,11 @@ def _emit(self, type: TokenType, value: str, line: int, column: int = 0) -> None
220222
"""Emit a token with the given type and value at the specified line and column."""
221223
self._tokens.append(Token(type, value, line, column))
222224

223-
def _read_until(self, condition: str | Callable[[str], bool], *, or_eof: bool = True) -> str:
225+
def _read_conditional(self, condition: Callable[[str], bool], *, or_eof: bool = True) -> str:
224226
"""Read until the current character matches the condition.
225227
226228
Args:
227-
condition: Characters to match, or a function that returns ``True`` to stop.
229+
condition: A function that returns ``True`` to stop.
228230
or_eof: If True, also stop if EOF is reached. If False, EOF will not stop the read and will raise an error.
229231
"""
230232
start = self._pos
@@ -234,47 +236,42 @@ def _read_until(self, condition: str | Callable[[str], bool], *, or_eof: bool =
234236
self._assert_not_eof()
235237
break
236238

237-
ch = self.data[self._pos]
238-
if isinstance(condition, str):
239-
if ch in condition:
240-
break
241-
else:
242-
if condition(ch):
243-
break
239+
if condition(self.data[self._pos]):
240+
break
244241

245242
self._pos += 1
246243

247244
end = self._pos
248245
self._pos = start
249246
return self._take(end - start)
250247

248+
def _read_until(self, condition: str | Callable[[str], bool], *, or_eof: bool = True) -> str:
249+
"""Read until the current character matches the condition.
250+
251+
Args:
252+
condition: Characters to match, or a function that returns ``True`` to stop.
253+
or_eof: If True, also stop if EOF is reached. If False, EOF will not stop the read and will raise an error.
254+
"""
255+
if isinstance(condition, str):
256+
condition = functools.partial(operator.contains, condition)
257+
258+
return self._read_conditional(condition, or_eof=or_eof)
259+
251260
def _read_while(self, condition: str | Callable[[str], bool], *, or_eof: bool = True) -> str:
252261
"""Read while the current character matches the condition.
253262
254263
Args:
255264
condition: Characters to match, or a function that returns ``True`` to continue.
256265
or_eof: If True, also stop if EOF is reached. If False, EOF will not stop the read and will raise an error.
257266
"""
258-
start = self._pos
259-
while True:
260-
if self.eof:
261-
if not or_eof:
262-
self._assert_not_eof()
263-
break
264267

265-
ch = self.data[self._pos]
266-
if isinstance(condition, str):
267-
if ch not in condition:
268-
break
269-
else:
270-
if not condition(ch):
271-
break
268+
def _invert(condition: Callable[[str], bool], ch: str) -> bool:
269+
return not condition(ch)
272270

273-
self._pos += 1
271+
if isinstance(condition, str):
272+
condition = functools.partial(operator.contains, condition)
274273

275-
end = self._pos
276-
self._pos = start
277-
return self._take(end - start)
274+
return self._read_conditional(functools.partial(_invert, condition), or_eof=or_eof)
278275

279276
def _skip_whitespace(self) -> None:
280277
"""Skip whitespace characters."""

0 commit comments

Comments
 (0)