/// <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);
        }
Beispiel #2
0
        /// <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);
        }