Exemplo n.º 1
0
        public InMemoryMetadataStream(IIndexItem item, XmlDocument doc)
        {
            var gen3Cache = item.CacheFile as IGen3CacheFile;

            if (gen3Cache == null)
            {
                throw new ArgumentException("Cache must implement IGen3CacheFile.");
            }

            segmenter = new CacheSegmenter(gen3Cache);

            SourceItem = item;
            AllBlocks  = new List <InMemoryBlockCollection>();

            using (var reader = item.CacheFile.CreateReader(item.CacheFile.DefaultAddressTranslator))
            {
                var expander = (item.CacheFile as IMccCacheFile)?.PointerExpander;
                if (expander != null)
                {
                    reader.RegisterInstance(expander);
                }

                reader.Seek(item.MetaPointer.Address, SeekOrigin.Begin);
                RootBlock = ReadBlocks(reader, doc.DocumentElement, null, 0);
            }

            currentBlock = AllBlocks.FirstOrDefault(b => b.ContainsVirtualAddress(position));

            isInitialised = true;
        }
Exemplo n.º 2
0
        private InMemoryBlockCollection ReadBlocks(EndianReader reader, XmlNode node, InMemoryBlockCollection parent, int parentBlockIndex)
        {
            var result = new InMemoryBlockCollection(this, reader, node, parent, parentBlockIndex);

            var lastBlock   = AllBlocks.LastOrDefault();
            var nextAddress = (lastBlock?.VirtualAddress + lastBlock?.AllocatedSize) ?? 0;
            var nextSize    = PageSize;

            while (nextSize < result.VirtualSize)
            {
                nextSize += PageSize;
            }

            result.Allocate(nextAddress, nextSize);
            AllBlocks.Add(result);

            var blockAddress = parent == null
                ? SourceItem.MetaPointer.Address
                : result.BlockRef.Pointer.Address;

            for (int i = 0; i < result.EntryCount; i++)
            {
                var indexAddress = blockAddress + result.EntrySize * i;
                foreach (var childNode in node.SelectNodes("tagblock").OfType <XmlNode>())
                {
                    reader.Seek(indexAddress + childNode.GetIntAttribute("offset").Value, SeekOrigin.Begin);
                    ReadBlocks(reader, childNode, result, i);
                }
            }

            return(result);
        }
Exemplo 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);
            }
        }