/// <summary> /// Resizes a block of tag data, updating relative pointers which do not point into the block. /// </summary> /// <param name="stream">The stream to write to.</param> /// <param name="tag">The tag.</param> /// <param name="startOffset">The offset, from the start of the tag's data, where the block to resize begins at.</param> /// <param name="oldSize">The current size of the block to resize.</param> /// <param name="newSize">The new size of the block.</param> /// <param name="origin">The origin where data should be inserted or removed.</param> public void ResizeTagData(Stream stream, TagInstance tag, long startOffset, long oldSize, long newSize, ResizeOrigin origin) { if (tag == null) throw new ArgumentNullException("tag"); if (tag.HeaderOffset < 0) throw new ArgumentException("The tag is not in the cache file"); if (oldSize < 0) throw new ArgumentException("The old block size cannot be negative"); if (newSize < 0) throw new ArgumentException("Cannot resize a block to a negative size"); if (newSize == tag.DataSize) return; // Correct offsets pointing after the block var sizeDelta = newSize - oldSize; var blockEndOffset = startOffset + oldSize; tag.DataSize += sizeDelta; foreach (var fixup in tag.DataFixups.Concat(tag.ResourceFixups)) { if (fixup.WriteOffset >= blockEndOffset) fixup.WriteOffset = (uint)(fixup.WriteOffset + sizeDelta); if (fixup.TargetOffset >= blockEndOffset) fixup.TargetOffset = (uint)(fixup.TargetOffset + sizeDelta); } if (tag.MainStructOffset >= blockEndOffset) tag.MainStructOffset = (uint)(tag.MainStructOffset + sizeDelta); FixTagOffsets(tag.DataOffset + blockEndOffset, sizeDelta, tag); // Insert/remove the data long editOffset; if (origin == ResizeOrigin.Beginning) editOffset = startOffset; else if (sizeDelta > 0) editOffset = blockEndOffset; else editOffset = blockEndOffset + sizeDelta; stream.Position = tag.DataOffset + editOffset; if (sizeDelta > 0) StreamUtil.Insert(stream, (int)sizeDelta, 0); else StreamUtil.Remove(stream, (int)-sizeDelta); UpdateTag(stream, tag); }
/// <summary> /// Resizes a block of tag data, updating relative pointers which do not point into the block. /// </summary> /// <param name="stream">The stream to write to.</param> /// <param name="tag">The tag.</param> /// <param name="startOffset">The offset, from the start of the tag's data, where the block to resize begins at.</param> /// <param name="oldSize">The current size of the block to resize.</param> /// <param name="newSize">The new size of the block.</param> /// <param name="origin">The origin where data should be inserted or removed.</param> public void ResizeTagData(Stream stream, TagInstance tag, long startOffset, long oldSize, long newSize, ResizeOrigin origin) { if (tag == null) { throw new ArgumentNullException("tag"); } if (tag.HeaderOffset < 0) { throw new ArgumentException("The tag is not in the cache file"); } if (oldSize < 0) { throw new ArgumentException("The old block size cannot be negative"); } if (newSize < 0) { throw new ArgumentException("Cannot resize a block to a negative size"); } if (newSize == tag.DataSize) { return; } // Correct offsets pointing after the block var sizeDelta = newSize - oldSize; var blockEndOffset = startOffset + oldSize; tag.DataSize += sizeDelta; foreach (var fixup in tag.DataFixups.Concat(tag.ResourceFixups)) { if (fixup.WriteOffset >= blockEndOffset) { fixup.WriteOffset = (uint)(fixup.WriteOffset + sizeDelta); } if (fixup.TargetOffset >= blockEndOffset) { fixup.TargetOffset = (uint)(fixup.TargetOffset + sizeDelta); } } if (tag.MainStructOffset >= blockEndOffset) { tag.MainStructOffset = (uint)(tag.MainStructOffset + sizeDelta); } FixTagOffsets(tag.DataOffset + blockEndOffset, sizeDelta, tag); // Insert/remove the data long editOffset; if (origin == ResizeOrigin.Beginning) { editOffset = startOffset; } else if (sizeDelta > 0) { editOffset = blockEndOffset; } else { editOffset = blockEndOffset + sizeDelta; } stream.Position = tag.DataOffset + editOffset; if (sizeDelta > 0) { StreamUtil.Insert(stream, (int)sizeDelta, 0); } else { StreamUtil.Remove(stream, (int)-sizeDelta); } UpdateTag(stream, tag); }