def __save_new(self, fileobj, atoms, ilst_data, padding_func): hdlr = Atom.render(b"hdlr", b"\x00" * 8 + b"mdirappl" + b"\x00" * 9) meta_data = b"\x00\x00\x00\x00" + hdlr + ilst_data try: path = atoms.path(b"moov", b"udta") except KeyError: path = atoms.path(b"moov") offset = path[-1]._dataoffset # ignoring some atom overhead... but we don't have padding left anyway # and padding_size is guaranteed to be less than zero content_size = get_size(fileobj) - offset padding_size = -len(meta_data) assert padding_size < 0 info = PaddingInfo(padding_size, content_size) new_padding = info._get_padding(padding_func) new_padding = min(0xFFFFFFFF, new_padding) free = Atom.render(b"free", b"\x00" * new_padding) meta = Atom.render(b"meta", meta_data + free) if path[-1].name != b"udta": # moov.udta not found -- create one data = Atom.render(b"udta", meta) else: data = meta insert_bytes(fileobj, len(data), offset) fileobj.seek(offset) fileobj.write(data) self.__update_parents(fileobj, path, len(data)) self.__update_offsets(fileobj, atoms, len(data), offset)
def __save_existing(self, fileobj, atoms, path, ilst_data, padding_func): # Replace the old ilst atom. ilst = path[-1] offset = ilst.offset length = ilst.length # Use adjacent free atom if there is one free = _find_padding(path) if free is not None: offset = min(offset, free.offset) length += free.length # Always add a padding atom to make things easier padding_overhead = len(Atom.render(b"free", b"")) content_size = get_size(fileobj) - (offset + length) padding_size = length - (len(ilst_data) + padding_overhead) info = PaddingInfo(padding_size, content_size) new_padding = info._get_padding(padding_func) # Limit padding size so we can be sure the free atom overhead is as we # calculated above (see Atom.render) new_padding = min(0xFFFFFFFF, new_padding) ilst_data += Atom.render(b"free", b"\x00" * new_padding) resize_bytes(fileobj, length, len(ilst_data), offset) delta = len(ilst_data) - length fileobj.seek(offset) fileobj.write(ilst_data) self.__update_parents(fileobj, path[:-1], delta) self.__update_offsets(fileobj, atoms, delta, offset)
def test_props(self): info = PaddingInfo(10, 100) self.assertEqual(info.size, 100) self.assertEqual(info.padding, 10) info = PaddingInfo(-10, 100) self.assertEqual(info.size, 100) self.assertEqual(info.padding, -10)
def test_default_strategy(self): s = 100000 self.assertEqual(PaddingInfo(10, s).get_default_padding(), 10) self.assertEqual(PaddingInfo(-10, s).get_default_padding(), 1124) self.assertEqual(PaddingInfo(0, s).get_default_padding(), 0) self.assertEqual(PaddingInfo(20000, s).get_default_padding(), 1124) self.assertEqual(PaddingInfo(10, 0).get_default_padding(), 10) self.assertEqual(PaddingInfo(-10, 0).get_default_padding(), 1024) self.assertEqual(PaddingInfo(1050, 0).get_default_padding(), 1050) self.assertEqual(PaddingInfo(20000, 0).get_default_padding(), 1024)
def test_repr(self): info = PaddingInfo(10, 100) self.assertEqual(repr(info), "<PaddingInfo size=100 padding=10>")