@@ -94,7 +94,13 @@ def _human_colors() -> dict[str, str]:
9494
9595
9696def _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 ,
98104) -> Iterator [str ]:
99105 """Hexdump some data.
100106
@@ -104,6 +110,7 @@ def _hexdump(
104110 offset: Byte offset of the hexdump.
105111 prefix: Optional prefix.
106112 pretty: Use pretty colors, mutual exclusive with palette.
113+ autoskip: A single '*' replaces NUL-lines in the output.
107114 """
108115 if palette :
109116 palette = palette [::- 1 ]
@@ -114,6 +121,9 @@ def _hexdump(
114121
115122 remaining = 0
116123 active = None
124+ in_null_run = False
125+ in_collapsed_null_run = False
126+ last_offset = len (data ) - 16
117127
118128 for i in range (0 , len (data ), 16 ):
119129 values = ""
@@ -166,17 +176,32 @@ def _hexdump(
166176 if j == 7 :
167177 values += " "
168178
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+
169192 chars = "" .join (chars )
170193 yield f"{ prefix } { offset + i :08x} { values :48s} { chars } "
171194
172195
173196def hexdump (
174197 data : bytes ,
198+ * ,
175199 palette : Palette | None = None ,
176200 offset : int = 0 ,
177201 prefix : str = "" ,
178202 output : str = "print" ,
179203 pretty : bool | None = None ,
204+ autoskip : bool = False ,
180205) -> Iterator [str ] | str | None :
181206 """Hexdump some data.
182207
@@ -190,6 +215,7 @@ def hexdump(
190215 prefix: Optional prefix.
191216 output: Output format, can be 'print', 'generator' or 'string'.
192217 pretty: Use pretty colors for improved human readability.
218+ autoskip: A single '*' replaces NUL-lines in the output.
193219 """
194220 # Enable pretty colors by default if ...
195221 if (
@@ -200,7 +226,7 @@ def hexdump(
200226 ):
201227 pretty = True
202228
203- generator = _hexdump (data , palette , offset , prefix , pretty )
229+ generator = _hexdump (data , palette = palette , offset = offset , prefix = prefix , pretty = pretty , autoskip = autoskip )
204230 if output == "print" :
205231 print ("\n " .join (generator ))
206232 return None
@@ -217,6 +243,7 @@ def _dumpstruct(
217243 offset : int ,
218244 color : bool ,
219245 output : str ,
246+ autoskip : bool ,
220247) -> str | None :
221248 palette = []
222249 colors = [
@@ -258,11 +285,11 @@ def _dumpstruct(
258285
259286 if output == "print" :
260287 print ()
261- hexdump (data , palette , offset = offset )
288+ hexdump (data , palette = palette , offset = offset , autoskip = autoskip )
262289 print ()
263290 print (out )
264291 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 } "
266293 return None
267294
268295
@@ -271,6 +298,7 @@ def dumpstruct(
271298 data : bytes | None = None ,
272299 offset : int = 0 ,
273300 color : bool = True ,
301+ autoskip : bool = False ,
274302 output : str = "print" ,
275303) -> str | None :
276304 """Dump a structure or parsed structure instance.
@@ -281,15 +309,17 @@ def dumpstruct(
281309 obj: Structure to dump.
282310 data: Bytes to parse the Structure on, if obj is not a parsed Structure already.
283311 offset: Byte offset of the hexdump.
312+ color: Colorize the hexdump and structure output.
313+ autoskip: A single '*' replaces NUL-lines in the output.
284314 output: Output format, can be 'print' or 'string'.
285315 """
286316 if output not in ("print" , "string" ):
287317 raise ValueError (f"Invalid output argument: { output !r} (should be 'print' or 'string')." )
288318
289319 if isinstance (obj , Structure ):
290- return _dumpstruct (obj , obj .dumps (), offset , color , output )
320+ return _dumpstruct (obj , obj .dumps (), offset , color , output , autoskip )
291321 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 )
293323 raise ValueError ("Invalid arguments" )
294324
295325
0 commit comments