Exemplo n.º 1
0
        /// <summary>
        /// Reads a tag's data from the file.
        /// </summary>
        /// <param name="stream">The stream to read from.</param>
        /// <param name="tag">The tag to read.</param>
        /// <returns>The data that was read.</returns>
        public CachedTagData ExtractTag(Stream stream, CachedTagInstance tag)
        {
            if (tag == null)
            {
                throw new ArgumentNullException(nameof(tag));
            }
            else if (tag.HeaderOffset < 0)
            {
                throw new ArgumentException("The tag is not in the cache file");
            }

            // Build the description info and get the data offset
            var data = BuildTagData(stream, tag, out uint dataOffset);

            // Read the tag data
            stream.Position = tag.HeaderOffset + dataOffset;
            data.Data       = new byte[tag.TotalSize - dataOffset];
            stream.Read(data.Data, 0, data.Data.Length);

            // Correct pointers
            using (var dataWriter = new BinaryWriter(new MemoryStream(data.Data)))
            {
                foreach (var fixup in data.PointerFixups)
                {
                    dataWriter.BaseStream.Position = fixup.WriteOffset;
                    dataWriter.Write(tag.OffsetToPointer(fixup.TargetOffset));
                }
            }
            return(data);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Overwrites a tag's data.
        /// </summary>
        /// <param name="stream">The stream to write to.</param>
        /// <param name="tag">The tag to overwrite.</param>
        /// <param name="data">The data to store.</param>
        public void SetTagData(Stream stream, CachedTagInstance tag, CachedTagData data)
        {
            if (tag == null)
            {
                throw new ArgumentNullException(nameof(tag));
            }
            else if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            else if (data.Group == TagGroup.None)
            {
                throw new ArgumentException("Cannot assign a tag to a null tag group");
            }
            else if (data.Data == null)
            {
                throw new ArgumentException("The tag data buffer is null");
            }

            // Ensure the data fits
            var headerSize        = CachedTagInstance.CalculateHeaderSize(data);
            var alignedHeaderSize = (uint)((headerSize + 0xF) & ~0xF);

            if (tag.HeaderOffset < 0)
            {
                tag.HeaderOffset = GetNewTagOffset(tag.Index);
            }
            var alignedLength = (data.Data.Length + 0xF) & ~0xF;

            ResizeBlock(stream, tag, tag.HeaderOffset, tag.TotalSize, alignedHeaderSize + alignedLength);
            tag.TotalSize = alignedHeaderSize + alignedLength;
            tag.Update(data, alignedHeaderSize);

            // Write in the new header and data
            stream.Position = tag.HeaderOffset;
            var writer = new BinaryWriter(stream);

            tag.WriteHeader(writer);
            StreamUtil.Fill(stream, 0, (int)(alignedHeaderSize - headerSize));
            stream.Write(data.Data, 0, data.Data.Length);
            StreamUtil.Fill(stream, 0, alignedLength - data.Data.Length);

            // Correct pointers
            foreach (var fixup in data.PointerFixups)
            {
                writer.BaseStream.Position = tag.HeaderOffset + alignedHeaderSize + fixup.WriteOffset;
                writer.Write(tag.OffsetToPointer(alignedHeaderSize + fixup.TargetOffset));
            }

            UpdateTagOffsets(writer);
        }