Ejemplo n.º 1
0
        public static void CloneBlobHeap(IMetadataStream stream, IBinaryStreamWriter writer,
                                         IndexBlobAction indexAction)
        {
            if (!stream.CanRead)
            {
                throw new ArgumentException("Stream to clone must be readable.");
            }

            var reader = stream.CreateReader();

            // Only copy first byte to output stream if we have already written something to the output stream.
            byte b = reader.ReadByte();

            if (writer.Length != 1)
            {
                writer.WriteByte(b);
            }

            // Perform linear sweep of the raw data.

            // Note: This might result in incorrect blob being indexed if garbage data was injected in the heap.
            //       This is okay as long as we still copy all the data, including the garbage data.
            //       The only side-effect we get is that blobs that did appear in the original stream might
            //       be duplicated in the new stream. This is an acceptable side-effect, as the purpose of this
            //       import function is to only preserve existing data, and not necessarily make sure that we use
            //       the most efficient storage mechanism.

            uint index = 1;

            while (index < stream.GetPhysicalSize())
            {
                ulong startOffset = reader.Offset;
                if (!reader.TryReadCompressedUInt32(out uint dataLength))
                {
                    break;
                }

                uint headerLength = (uint)(reader.Offset - startOffset);
                reader.Offset -= headerLength;

                if (dataLength > 0)
                {
                    indexAction(index, writer.Length);
                }

                // Copy over raw data of blob to output stream.
                // This is important since technically it is possible to encode the same blob in multiple ways.
                var buffer       = new byte[headerLength + dataLength];
                int actualLength = reader.ReadBytes(buffer, 0, buffer.Length);

                writer.WriteBytes(buffer, 0, actualLength);

                // Move to next blob.
                index += (uint)actualLength;
            }
        }
        public virtual async Task <string> RegisterStream(IMetadataStream stream, DateTime?startTime = null)
        {
            if (!stream.IsRunning)
            {
                await stream.Start(startTime);
            }

            var id = Guid.NewGuid().ToString();

            _streams.TryAdd(id, stream);

            return(await Task.FromResult(id));
        }
Ejemplo n.º 3
0
        public InMemoryBlockCollection(IMetadataStream stream, EndianReader reader, XmlNode node, InMemoryBlockCollection parent, int parentBlockIndex)
        {
            this.stream   = stream;
            defaultValues = new Dictionary <int, byte[]>();

            XmlNode          = node;
            ParentBlock      = parent;
            ParentEntryIndex = parentBlockIndex;
            ChildBlocks      = new List <InMemoryBlockCollection>();
            ParentBlock?.ChildBlocks.Add(this);

            if (parent == null) //tag root
            {
                Name       = stream.SourceTag.FileName();
                blockRef   = null;
                EntryCount = 1;
                EntrySize  = node.GetIntAttribute("baseSize") ?? 0;
                data       = reader.ReadBytes(VirtualSize);
            }
            else
            {
                offsetInParent = node.GetIntAttribute("offset") ?? 0;
                Name           = node.GetStringAttribute("name");
                blockRef       = reader.ReadObject <TagBlock>();
                EntryCount     = BlockRef.IsInvalid ? 0 : BlockRef.Count;
                EntrySize      = node.GetIntAttribute("elementSize", "entrySize", "size") ?? 0;

                if (EntryCount > 0)
                {
                    reader.Seek(BlockRef.Pointer.Address, SeekOrigin.Begin);
                    data = reader.ReadBytes(VirtualSize);
                }
                else
                {
                    data = Array.Empty <byte>();
                }
            }

            foreach (var element in node.SelectNodes("*[@offset][@defaultValue]").OfType <XmlNode>())
            {
                var offset       = element.GetIntAttribute("offset").Value;
                var defaultValue = element.GetStringAttribute("defaultValue");

                Func <string, int> getFlagValue = (val) => val.Split('|').Select(s => 1 << int.Parse(s)).Sum();

                byte[] bytes;
                switch (element.Name.ToLower())
                {
                case "int8":
                case "enum8":
                case "blockindex8":
                    bytes = new[] { defaultValue == "-1" ? byte.MaxValue : byte.Parse(defaultValue) };
                    break;

                case "int16":
                case "blockindex16":
                    bytes = BitConverter.GetBytes(short.Parse(defaultValue));
                    break;

                case "uint16":
                case "enum16":
                    bytes = BitConverter.GetBytes(ushort.Parse(defaultValue));
                    break;

                case "int32":
                case "blockindex32":
                    bytes = BitConverter.GetBytes(int.Parse(defaultValue));
                    break;

                case "uint32":
                case "enum32":
                    bytes = BitConverter.GetBytes(uint.Parse(defaultValue));
                    break;

                case "float32":
                    bytes = BitConverter.GetBytes(float.Parse(defaultValue));
                    break;

                case "flags8":
                    bytes = BitConverter.GetBytes((byte)getFlagValue(defaultValue));
                    break;

                case "flags16":
                    bytes = BitConverter.GetBytes((ushort)getFlagValue(defaultValue));
                    break;

                case "flags32":
                    bytes = BitConverter.GetBytes((uint)getFlagValue(defaultValue));
                    break;

                default:
                    continue;
                }

                if (stream.ByteOrder == ByteOrder.BigEndian)
                {
                    Array.Reverse(bytes);
                }

                defaultValues.Add(offset, bytes);
            }
        }