def seek_temporary(stream: IO[Any], path: str, offset: int) -> Iterator[None]: ''' Context manager which seeks to the specified offset on entering, and seeks back to the original offset on exit ''' fallback = stream_tell(stream, path) stream_seek(stream, offset, 0, path) yield stream_seek(stream, fallback, 0, path)
def _parse(self, stream, context, path): # Get Index if we are in an Array, Sequence, ... if hasattr(context, "_index"): index = context._index else: index = None offset_start = cs.stream_tell(stream, path) obj = self.subcon._parsereport(stream, context, path) # type: ignore offset_end = cs.stream_tell(stream, path) gui_metadata = GuiMetaData( offset_start=offset_start, offset_end=offset_end, length=offset_end - offset_start, construct=self.subcon, index=index, context=context, ) return add_gui_metadata(obj, gui_metadata)
def get_offset_in_outer_stream(stream, context, path): ''' Tries to calculate the current offset in the outermost stream by traversing the context tree. This is very likely to go completely wrong in many configurations; right now it takes streams in other contexts and the :class:`Prefixed` type into account. ''' offset = stream_tell(stream, path) # collect offsets of enclosing streams by walking up the tree prev_stream = stream for c in iter_context_tree(context): curr_stream = getattr(c, '_io', None) if curr_stream is None: break # add to offset if stream changed if curr_stream is not prev_stream: offset += stream_tell(curr_stream, path) prev_stream = curr_stream # the Prefixed type writes the length _after_ building the subcon (which makes sense), # but that also means that the current data will be written at [current offset] + [size of length field], # which has to be taken into account as the stream's offset doesn't include the length field yet stack = inspect.stack() try: for info in stack: if info.function != '_build': continue local_self = info.frame.f_locals.get('self') if isinstance(local_self, Prefixed): offset += local_self.lengthfield.sizeof() finally: del stack # just to be safe, see https://docs.python.org/3/library/inspect.html#the-interpreter-stack return offset
def stream_tell(stream, path): return C.stream_tell(stream, path)
def _pad(self, stream, path): v = self.modulus - 1 pos = stream_tell(stream, path) newpos = (pos + v) & ~v return newpos - pos