# fileutil.py """Functions for reading to certain bytes, e.g. delimiters""" # Copyright (c) 2009-2012 Darcy Mason # This file is part of pydicom, released under a modified MIT license. # See the file license.txt included with this distribution, also # available at http://pydicom.googlecode.com from struct import pack, unpack from dicom.tag import TupleTag, Tag from dicom.datadict import dictionary_description import logging logger = logging.getLogger('pydicom') def absorb_delimiter_item(fp, is_little_endian, delimiter): """Read (and ignore) undefined length sequence or item terminators.""" if is_little_endian: struct_format = "HH" bytes_to_find = pack(bytes_format, delimiter_tag.group, delimiter_tag.elem) found = False EOF = False value_chunks = [] byte_count = 0 # for defer_size checks while not found: chunk_start = fp.tell() bytes_read = fp.read(read_size) if len(bytes_read) < read_size: # try again - if still don't get required amount, this is last block new_bytes = fp.read(read_size - len(bytes_read)) bytes_read += new_bytes if len(bytes_read) < read_size: EOF = True # but will still check whatever we did get index = bytes_read.find(bytes_to_find) if index != -1: found = True new_bytes = bytes_read[:index] byte_count += len(new_bytes) if defer_size is None or byte_count < defer_size: value_chunks.append(bytes_read[:index]) fp.seek(chunk_start + index + 4) # rewind to end of delimiter length = fp.read(4) if length != b"\0\0\0\0": msg = "Expected 4 zero bytes after undefined length delimiter at pos {0:04x}" logger.error(msg.format(fp.tell() - 4)) elif EOF: fp.seek(data_start) raise EOFError("End of file reached before delimiter {0!r} found".format(delimiter_tag)) else: fp.seek(fp.tell() - search_rewind) # rewind a bit in case delimiter crossed read_size boundary # accumulate the bytes read (not including the rewind) new_bytes = bytes_read[:-search_rewind] byte_count += len(new_bytes) if defer_size is None or byte_count < defer_size: value_chunks.append(new_bytes) # if get here then have found the byte string if defer_size is not None and defer_size >= defer_size: return None else: return b"".join(value_chunks) def find_delimiter(fp, delimiter, is_little_endian, read_size=128, rewind=True): """Return file position where 4-byte delimiter is located. Return None if reach end of file without finding the delimiter. On return, file position will be where it was before this function, unless rewind argument is False. """ struct_format = "