dissect.cstruct 4.8.dev7__py3-none-any.whl → 4.8.dev8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
dissect/cstruct/utils.py CHANGED
@@ -94,7 +94,13 @@ HUMAN_COLORS = _human_colors()
94
94
 
95
95
 
96
96
  def _hexdump(
97
- data: bytes, palette: Palette | None = None, offset: int = 0, prefix: str = "", pretty: bool | None = False
97
+ data: bytes,
98
+ *,
99
+ palette: Palette | None = None,
100
+ offset: int = 0,
101
+ prefix: str = "",
102
+ pretty: bool | None = False,
103
+ autoskip: bool = False,
98
104
  ) -> Iterator[str]:
99
105
  """Hexdump some data.
100
106
 
@@ -104,6 +110,7 @@ def _hexdump(
104
110
  offset: Byte offset of the hexdump.
105
111
  prefix: Optional prefix.
106
112
  pretty: Use pretty colors, mutual exclusive with palette.
113
+ autoskip: A single '*' replaces NUL-lines in the output.
107
114
  """
108
115
  if palette:
109
116
  palette = palette[::-1]
@@ -114,6 +121,9 @@ def _hexdump(
114
121
 
115
122
  remaining = 0
116
123
  active = None
124
+ in_null_run = False
125
+ in_collapsed_null_run = False
126
+ last_offset = len(data) - 16
117
127
 
118
128
  for i in range(0, len(data), 16):
119
129
  values = ""
@@ -166,17 +176,32 @@ def _hexdump(
166
176
  if j == 7:
167
177
  values += " "
168
178
 
179
+ if autoskip and 0 < i < last_offset and data[i : i + 16] == b"\x00" * 16:
180
+ if in_null_run:
181
+ if not in_collapsed_null_run:
182
+ yield "*"
183
+ in_collapsed_null_run = True
184
+ continue
185
+
186
+ # Keep the first interior NUL line visible, collapse from the second onwards.
187
+ in_null_run = True
188
+ else:
189
+ in_null_run = False
190
+ in_collapsed_null_run = False
191
+
169
192
  chars = "".join(chars)
170
193
  yield f"{prefix}{offset + i:08x} {values:48s} {chars}"
171
194
 
172
195
 
173
196
  def hexdump(
174
197
  data: bytes,
198
+ *,
175
199
  palette: Palette | None = None,
176
200
  offset: int = 0,
177
201
  prefix: str = "",
178
202
  output: str = "print",
179
203
  pretty: bool | None = None,
204
+ autoskip: bool = False,
180
205
  ) -> Iterator[str] | str | None:
181
206
  """Hexdump some data.
182
207
 
@@ -190,6 +215,7 @@ def hexdump(
190
215
  prefix: Optional prefix.
191
216
  output: Output format, can be 'print', 'generator' or 'string'.
192
217
  pretty: Use pretty colors for improved human readability.
218
+ autoskip: A single '*' replaces NUL-lines in the output.
193
219
  """
194
220
  # Enable pretty colors by default if ...
195
221
  if (
@@ -200,7 +226,7 @@ def hexdump(
200
226
  ):
201
227
  pretty = True
202
228
 
203
- generator = _hexdump(data, palette, offset, prefix, pretty)
229
+ generator = _hexdump(data, palette=palette, offset=offset, prefix=prefix, pretty=pretty, autoskip=autoskip)
204
230
  if output == "print":
205
231
  print("\n".join(generator))
206
232
  return None
@@ -217,6 +243,7 @@ def _dumpstruct(
217
243
  offset: int,
218
244
  color: bool,
219
245
  output: str,
246
+ autoskip: bool,
220
247
  ) -> str | None:
221
248
  palette = []
222
249
  colors = [
@@ -258,11 +285,11 @@ def _dumpstruct(
258
285
 
259
286
  if output == "print":
260
287
  print()
261
- hexdump(data, palette, offset=offset)
288
+ hexdump(data, palette=palette, offset=offset, autoskip=autoskip)
262
289
  print()
263
290
  print(out)
264
291
  elif output == "string":
265
- return f"\n{hexdump(data, palette, offset=offset, output='string')}\n\n{out}"
292
+ return f"\n{hexdump(data, palette=palette, offset=offset, output='string', autoskip=autoskip)}\n\n{out}"
266
293
  return None
267
294
 
268
295
 
@@ -271,6 +298,7 @@ def dumpstruct(
271
298
  data: bytes | None = None,
272
299
  offset: int = 0,
273
300
  color: bool = True,
301
+ autoskip: bool = False,
274
302
  output: str = "print",
275
303
  ) -> str | None:
276
304
  """Dump a structure or parsed structure instance.
@@ -281,15 +309,17 @@ def dumpstruct(
281
309
  obj: Structure to dump.
282
310
  data: Bytes to parse the Structure on, if obj is not a parsed Structure already.
283
311
  offset: Byte offset of the hexdump.
312
+ color: Colorize the hexdump and structure output.
313
+ autoskip: A single '*' replaces NUL-lines in the output.
284
314
  output: Output format, can be 'print' or 'string'.
285
315
  """
286
316
  if output not in ("print", "string"):
287
317
  raise ValueError(f"Invalid output argument: {output!r} (should be 'print' or 'string').")
288
318
 
289
319
  if isinstance(obj, Structure):
290
- return _dumpstruct(obj, obj.dumps(), offset, color, output)
320
+ return _dumpstruct(obj, obj.dumps(), offset, color, output, autoskip)
291
321
  if issubclass(obj, Structure) and data is not None:
292
- return _dumpstruct(obj(data), data, offset, color, output)
322
+ return _dumpstruct(obj(data), data, offset, color, output, autoskip)
293
323
  raise ValueError("Invalid arguments")
294
324
 
295
325
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.cstruct
3
- Version: 4.8.dev7
3
+ Version: 4.8.dev8
4
4
  Summary: A Dissect module implementing a parser for C-like structures: structure parsing in Python made easy
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License-Expression: Apache-2.0
@@ -5,7 +5,7 @@ dissect/cstruct/cstruct.py,sha256=1lHbxZwj5x2EmmXLR0sJlp-wQqaTtd_ht1lvwit0KtQ,19
5
5
  dissect/cstruct/exceptions.py,sha256=SX05-_HqQn8lYC7SBHv5OrYEepYRMNmRiIzVPW8bvMQ,330
6
6
  dissect/cstruct/expression.py,sha256=mf5GFGLAn_2Tz3QK86Yqoi317l8cjMcffBKzP2STE6M,10841
7
7
  dissect/cstruct/parser.py,sha256=Mk8QbkDov_xfauZnp2MqUmFGOPZlp7O2rSLYbB9S3g4,24550
8
- dissect/cstruct/utils.py,sha256=09np2dWkiZwhQQAoFRf-Yo8bhvtl-TRWLuYQlbQLD4c,13118
8
+ dissect/cstruct/utils.py,sha256=jSWZY8AWoLHF1W9ix-7EH2eI7pTHzLfnSfQHWH1qgKM,14190
9
9
  dissect/cstruct/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  dissect/cstruct/tools/stubgen.py,sha256=wvl07h3VnJZWe9ygX4QMxjEH1ZcWaI_6_pSdAJoOEXk,7820
11
11
  dissect/cstruct/types/__init__.py,sha256=6P71Pu94Dv7RNjZpDZ19pqzx-G0QzmQw4q0-3zWALso,911
@@ -20,10 +20,10 @@ dissect/cstruct/types/pointer.py,sha256=PqeJOoNBUfMd5uO2kpF6OHeW7Q6R1N1W1V4q1Mak
20
20
  dissect/cstruct/types/structure.py,sha256=I9LVeZ81rNE5GDT6wxpUL-PqMO31Ae6TVLLzTGyd6mM,33012
21
21
  dissect/cstruct/types/void.py,sha256=Gvh0HqI6jQSj2uesdo3J8-G41brWCz8pmP16l8xTBxE,1074
22
22
  dissect/cstruct/types/wchar.py,sha256=N9Y_XX2_hZEe2DwepJjxsB6xuRJ6zINRalcUofR59kY,2608
23
- dissect_cstruct-4.8.dev7.dist-info/licenses/COPYRIGHT,sha256=H-18RXfshdH9AdHwW2eO1Xa-5s6tY5eipHh5c0whDu4,316
24
- dissect_cstruct-4.8.dev7.dist-info/licenses/LICENSE,sha256=PhUqiw6jAh2KbBdVRPBq_hfAvfcTBin7nZ3CK7NQbTM,11341
25
- dissect_cstruct-4.8.dev7.dist-info/METADATA,sha256=_le4cpqgrJ3kEOhL-zq84L_ZrfNUKDtjMn85EIF3hrs,9255
26
- dissect_cstruct-4.8.dev7.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
27
- dissect_cstruct-4.8.dev7.dist-info/entry_points.txt,sha256=z53zqZqwD2OLrAkRwrP4wTeiU9CQe7xrMly0T2c0_wQ,71
28
- dissect_cstruct-4.8.dev7.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
29
- dissect_cstruct-4.8.dev7.dist-info/RECORD,,
23
+ dissect_cstruct-4.8.dev8.dist-info/licenses/COPYRIGHT,sha256=H-18RXfshdH9AdHwW2eO1Xa-5s6tY5eipHh5c0whDu4,316
24
+ dissect_cstruct-4.8.dev8.dist-info/licenses/LICENSE,sha256=PhUqiw6jAh2KbBdVRPBq_hfAvfcTBin7nZ3CK7NQbTM,11341
25
+ dissect_cstruct-4.8.dev8.dist-info/METADATA,sha256=LpS2_xD11bTw0F2YOz0X9ZWNDgptmNd_FcgzHnrR8nI,9255
26
+ dissect_cstruct-4.8.dev8.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
27
+ dissect_cstruct-4.8.dev8.dist-info/entry_points.txt,sha256=z53zqZqwD2OLrAkRwrP4wTeiU9CQe7xrMly0T2c0_wQ,71
28
+ dissect_cstruct-4.8.dev8.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
29
+ dissect_cstruct-4.8.dev8.dist-info/RECORD,,