|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
| 3 | +import copy |
3 | 4 | import ctypes as _ctypes |
4 | 5 | import struct |
5 | 6 | import sys |
|
25 | 26 | Void, |
26 | 27 | Wchar, |
27 | 28 | ) |
| 29 | +from dissect.cstruct.types.base import MetaType |
28 | 30 |
|
29 | 31 | if TYPE_CHECKING: |
30 | 32 | from collections.abc import Iterable |
@@ -206,6 +208,25 @@ def __getattr__(self, attr: str) -> Any: |
206 | 208 |
|
207 | 209 | raise AttributeError(f"Invalid attribute: {attr}") |
208 | 210 |
|
| 211 | + def __copy__(self) -> cstruct: |
| 212 | + cs = cstruct(endian=self.endian, pointer=self.pointer.__name__) |
| 213 | + cs._anonymous_count = self._anonymous_count |
| 214 | + cs.consts = self.consts.copy() |
| 215 | + cs.lookups = self.lookups.copy() |
| 216 | + cs.includes = self.includes.copy() |
| 217 | + |
| 218 | + # Update typedefs to point to the new cstruct instance |
| 219 | + for name, type in self.typedefs.items(): |
| 220 | + if name in cs.typedefs: |
| 221 | + continue |
| 222 | + |
| 223 | + if isinstance(type, MetaType): |
| 224 | + new_type = copy.copy(type) |
| 225 | + new_type.cs = cs |
| 226 | + cs.typedefs[name] = new_type |
| 227 | + |
| 228 | + return cs |
| 229 | + |
209 | 230 | def _next_anonymous(self) -> str: |
210 | 231 | name = f"__anonymous_{self._anonymous_count}__" |
211 | 232 | self._anonymous_count += 1 |
@@ -328,6 +349,14 @@ def resolve(self, name: type[BaseType] | str) -> type[BaseType]: |
328 | 349 |
|
329 | 350 | raise ResolveError(f"Recursion limit exceeded while resolving type {name}") |
330 | 351 |
|
| 352 | + def copy(self) -> cstruct: |
| 353 | + """Create a copy of this cstruct instance. |
| 354 | +
|
| 355 | + Returns: |
| 356 | + A new cstruct instance with the same types and settings as this one. |
| 357 | + """ |
| 358 | + return copy.copy(self) |
| 359 | + |
331 | 360 | def _make_type( |
332 | 361 | self, |
333 | 362 | name: str, |
|
0 commit comments