예제 #1
0
        protected void ReadTypeTreeNode(DumpReader reader, int indent)
        {
            Type = ReadType(reader);
            Name = ReadName(reader);

            reader.FindValidateWord("//");

            ByteSize = ReadHexIntParameter(reader, "ByteSize");
            reader.FindValidateLineWord(",");
            Index = ReadHexIntParameter(reader, "Index");
            reader.FindValidateLineWord(",");
            Version = ReadHexIntParameter(reader, "Version");
            reader.FindValidateLineWord(",");
            IsArray = ReadBoolParameter(reader, "IsArray");
            reader.FindValidateLineWord(",");
            MetaFlag = unchecked ((uint)ReadHexIntParameter(reader, "MetaFlag"));
            reader.FindValidateEOL();
            reader.FindNextLine();

            int childIndent = indent + 1;
            List <TreeNodeDump> children = new List <TreeNodeDump>();

            while (reader.PeekIndend() == childIndent)
            {
                TreeNodeDump child = new TreeNodeDump();
                child.ReadTypeTreeNode(reader, childIndent);
                children.Add(child);
            }
            Children = children.ToArray();
        }
예제 #2
0
        public virtual TreeNodeDump Optimize()
        {
            TreeNodeDump node = new TreeNodeDump();

            Optimize(node);
            return(node);
        }
예제 #3
0
        private TreeNodeDiff(TreeNodeDump node, bool left)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            Name = node.Name ?? throw new ArgumentNullException(nameof(node.Name));

            string type = node.Type ?? throw new ArgumentNullException(nameof(node.Type));

            LeftType  = left ? string.Empty : type;
            RightType = left ? type : string.Empty;

            LeftVersion  = left ? 0 : node.Version;
            RightVersion = left ? node.Version : 0;

            LeftAlign  = left ? false : node.IsAlign;
            RightAlign = left ? node.IsAlign : false;

            TreeNodeDiff[] children = node.Children.Select(t => new TreeNodeDiff(t, left)).ToArray();
            LeftChildren  = left ? children : new TreeNodeDiff[0];
            RightChildren = left ? new TreeNodeDiff[0] : children;

            Status = DeepStatus = DiffStatus.Changed;
        }
예제 #4
0
        public TreeNodeDiff(TreeNodeDump node, DiffStatus status)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }
            if (status != DiffStatus.Added && status != DiffStatus.Deleted)
            {
                throw new ArgumentException(nameof(status));
            }

            Name = node.Name ?? throw new ArgumentNullException(nameof(node.Name));

            string type = node.Type ?? throw new ArgumentNullException(nameof(node.Type));

            LeftType  = status == DiffStatus.Added ? string.Empty : type;
            RightType = status == DiffStatus.Added ? type : string.Empty;

            LeftVersion  = status == DiffStatus.Added ? 0 : node.Version;
            RightVersion = status == DiffStatus.Added ? node.Version : 0;

            LeftAlign  = status == DiffStatus.Added ? false : node.IsAlign;
            RightAlign = status == DiffStatus.Added ? node.IsAlign : false;

            int          childNodeCount = node.GetNodeCount() - 1;
            TreeNodeDiff emptyElement   = childNodeCount == 0 ? null : new TreeNodeDiff(status);

            TreeNodeDiff[] children      = node.Children.Select(t => new TreeNodeDiff(t, status)).ToArray();
            TreeNodeDiff[] emptyChildren = Enumerable.Repeat(emptyElement, childNodeCount).ToArray();
            LeftChildren  = status == DiffStatus.Added ? emptyChildren : children;
            RightChildren = status == DiffStatus.Added ? children : emptyChildren;

            Status = DeepStatus = status;
        }
예제 #5
0
 private static bool IsNodePresent(TreeNodeDump node, TreeNodeDump right, int startIndex)
 {
     for (int ri = startIndex + 1; ri < right.Children.Count; ri++)
     {
         TreeNodeDump rightChild = right.Children[ri];
         if (IsNodeSame(node, rightChild))
         {
             return(true);
         }
     }
     return(false);
 }
예제 #6
0
        private static TreeNodeDiff[] CreateChildren(TreeNodeDump left, TreeNodeDump right)
        {
            List <TreeNodeDiff> children = new List <TreeNodeDiff>();

            for (int li = 0, ri = 0; li < left.Children.Count || ri < right.Children.Count;)
            {
                if (li == left.Children.Count)
                {
                    TreeNodeDiff node = new TreeNodeDiff(right.Children[ri], DiffStatus.Added);
                    children.Add(node);
                    ri++;
                    continue;
                }
                if (ri == right.Children.Count)
                {
                    TreeNodeDiff node = new TreeNodeDiff(left.Children[li], DiffStatus.Deleted);
                    children.Add(node);
                    li++;
                    continue;
                }

                TreeNodeDump leftChild  = left.Children[li];
                TreeNodeDump rightChild = right.Children[ri];
                if (IsNodeSame(leftChild, rightChild))
                {
                    TreeNodeDiff node = new TreeNodeDiff(leftChild, rightChild);
                    children.Add(node);
                    li++;
                    ri++;
                    continue;
                }

                if (IsNodePresent(leftChild, right, ri))
                {
                    do
                    {
                        TreeNodeDiff node = new TreeNodeDiff(rightChild, DiffStatus.Added);
                        children.Add(node);
                        ri++;

                        rightChild = right.Children[ri];
                    } while (!IsNodeSame(leftChild, rightChild));
                }
                else
                {
                    TreeNodeDiff node = new TreeNodeDiff(leftChild, DiffStatus.Deleted);
                    children.Add(node);
                    li++;
                    continue;
                }
            }
            return(children.ToArray());
        }
예제 #7
0
 private void CopyTypeTreeNode(TreeNodeDump node, int indent, StringBuilder sb)
 {
     sb.Append('\t', indent).Append(node.Type).Append(' ').Append(node.Name);
     // Nice bug, C#. Look at this beautiful piece of... code
     sb.AppendFormat(" // ByteSize{0}{1:x}{2}, Index{3}{4:x}{5}, Version{6}{7:x}{8}, IsArray{{{9}}}, MetaFlag{10}{11:x}{12}",
                     "{", unchecked ((uint)node.ByteSize), "}",
                     "{", node.Index, "}",
                     "{", node.Version, "}",
                     node.IsArray ? 1 : 0,
                     "{", node.MetaFlag, "}").AppendLine();
     foreach (TreeNodeDump child in node.Children)
     {
         CopyTypeTreeNode(child, indent + 1, sb);
     }
 }
예제 #8
0
        private TreeNodeDiff(TreeNodeDump left, TreeNodeDump right, bool forceMerge)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }
            if (left.Name != right.Name)
            {
                throw new ArgumentException("Left and right names aren't equal");
            }

            Name         = left.Name ?? throw new ArgumentNullException(nameof(left.Name));
            LeftType     = left.Type ?? throw new ArgumentNullException(nameof(left.Type));
            RightType    = right.Type ?? throw new ArgumentNullException(nameof(left.Type));
            LeftVersion  = left.Version;
            RightVersion = right.Version;
            LeftAlign    = left.IsAlign;
            RightAlign   = right.IsAlign;
            Status       = (LeftType == RightType && LeftVersion == RightVersion && LeftAlign == RightAlign) ?
                           DiffStatus.Unchanged : DiffStatus.Changed;

            if (LeftType == RightType || forceMerge)
            {
                TreeNodeDiff[] children = CreateChildren(left, right);
                LeftChildren = RightChildren = children;
                DeepStatus   = children.All(t => t.DeepStatus == DiffStatus.Unchanged) ? Status : DiffStatus.Changed;
            }
            else
            {
                int          leftNodeCount  = left.GetNodeCount();
                int          rightNodeCount = right.GetNodeCount();
                int          extraLeft      = Math.Max(rightNodeCount - leftNodeCount, 0);
                int          extraRight     = Math.Max(leftNodeCount - rightNodeCount, 0);
                TreeNodeDiff extraElement   = leftNodeCount == rightNodeCount ? null : new TreeNodeDiff(DiffStatus.Changed);
                IEnumerable <TreeNodeDiff> extraLeftChildren  = Enumerable.Repeat(extraElement, extraLeft);
                IEnumerable <TreeNodeDiff> extraRightChildren = Enumerable.Repeat(extraElement, extraRight);

                LeftChildren  = left.Children.Select(t => new TreeNodeDiff(t, false)).Concat(extraLeftChildren).ToArray();
                RightChildren = right.Children.Select(t => new TreeNodeDiff(t, true)).Concat(extraRightChildren).ToArray();
                DeepStatus    = DiffStatus.Changed;
            }
        }
예제 #9
0
        protected void Optimize(TreeNodeDump dest)
        {
            string type = Type;

            dest.Type     = ToOptimizedType(this);
            dest.Name     = Name;
            dest.ByteSize = ByteSize;
            dest.Index    = Index;
            dest.Version  = Version;
            dest.IsArray  = IsArray;
            dest.MetaFlag = MetaFlag;

            IReadOnlyList <TreeNodeDump> children = GetOptimizedChildren();
            int childCount = children == null ? 0 : children.Count;

            TreeNodeDump[] newChildren = new TreeNodeDump[childCount];
            for (int i = 0; i < childCount; i++)
            {
                newChildren[i] = children[i].Optimize();
            }
            dest.Children = newChildren;
        }
예제 #10
0
        private static string ToOptimizedType(TreeNodeDump node)
        {
            string type = node.Type;
            IReadOnlyList <TreeNodeDump> children = node.Children;

            switch (type)
            {
            case "SInt8":
                return("sbyte");

            case "UInt8":
                return("byte");

            case "SInt16":
                return("short");

            case "UInt16":
                return("ushort");

            case "SInt32":
                return("int");

            case "UInt32":
                return("uint");

            case "unsigned int":
                return("uint");

            case "SInt64":
                return("long");

            case "UInt64":
                return("ulong");

            case "ColorRGBA":
            {
                if (children.Count == 1)
                {
                    TreeNodeDump rgba = children[0];
                    if (ToOptimizedType(rgba) != "uint")
                    {
                        throw new Exception($"ColorRGBA's data node type {rgba.Name} doesn't match expected value 'unsigned int'");
                    }
                    if (rgba.Name != "rgba")
                    {
                        throw new Exception($"ColorRGBA's data node name {rgba.Name} doesn't match expected value 'rgba'");
                    }
                    return("ColorRGBA32");
                }
                else if (children.Count == 4)
                {
                    TreeNodeDump r = children[0];
                    TreeNodeDump g = children[1];
                    TreeNodeDump b = children[2];
                    TreeNodeDump a = children[3];
                    if (r.Type != "float")
                    {
                        throw new Exception($"ColorRGBA's R color node type {r.Name} doesn't match expected value 'float'");
                    }
                    if (g.Type != "float")
                    {
                        throw new Exception($"ColorRGBA's G color node type {g.Name} doesn't match expected value 'float'");
                    }
                    if (b.Type != "float")
                    {
                        throw new Exception($"ColorRGBA's B color node type {b.Name} doesn't match expected value 'float'");
                    }
                    if (a.Type != "float")
                    {
                        throw new Exception($"ColorRGBA's A color node type {a.Name} doesn't match expected value 'float'");
                    }
                    if (r.Name != "r")
                    {
                        throw new Exception($"ColorRGBA's R color node name {r.Name} doesn't match expected value 'r'");
                    }
                    if (g.Name != "g")
                    {
                        throw new Exception($"ColorRGBA's R color node name {g.Name} doesn't match expected value 'g'");
                    }
                    if (b.Name != "b")
                    {
                        throw new Exception($"ColorRGBA's R color node name {b.Name} doesn't match expected value 'b'");
                    }
                    if (a.Name != "a")
                    {
                        throw new Exception($"ColorRGBA's R color node name {a.Name} doesn't match expected value 'a'");
                    }
                    return("ColorRGBAf");
                }
                else
                {
                    throw new Exception($"ColorRGBA has {children.Count} children but expected 1 or 4");
                }
            }

            case "vector":
            {
                if (children.Count != 1)
                {
                    throw new Exception($"Vector has {children.Count} children but expected 1");
                }

                TreeNodeDump array = children[0];
                if (array.Children.Count != 2)
                {
                    throw new Exception($"Vector's array node has {array.Children.Count} children but expected 2");
                }
                if (array.Type != "Array")
                {
                    throw new Exception($"Vector's array node type {array.Name} doesn't match expected value 'Array'");
                }
                if (array.Name != "Array")
                {
                    throw new Exception($"Vector's array node name {array.Name} doesn't match expected value 'Array'");
                }

                TreeNodeDump vectorSize = array.Children[0];
                if (ToOptimizedType(vectorSize) != "int")
                {
                    throw new Exception($"Vector's size node type {vectorSize.Type} doesn't match expected value 'int'");
                }
                if (vectorSize.Name != "size")
                {
                    throw new Exception($"Vector's size node name {vectorSize.Name} doesn't match expected value 'size'");
                }

                TreeNodeDump vectorValue = array.Children[1];
                if (vectorValue.Name != "data")
                {
                    throw new Exception($"Vector's value node name {vectorValue.Name} doesn't match expected value 'data'");
                }

                return($"{ToOptimizedType(vectorValue)}[]");
            }

            case "map":
            {
                if (children.Count != 1)
                {
                    throw new Exception($"Map has {children.Count} children but expected 1");
                }

                TreeNodeDump array = children[0];
                if (array.Children.Count != 2)
                {
                    throw new Exception($"Map's array node has {array.Children.Count} children but expected 2");
                }
                if (array.Type != "Array")
                {
                    throw new Exception($"Map's array node type {array.Name} doesn't match expected value 'Array'");
                }
                if (array.Name != "Array")
                {
                    throw new Exception($"Map's array node name {array.Name} doesn't match expected value 'Array'");
                }

                TreeNodeDump mapSize = array.Children[0];
                if (ToOptimizedType(mapSize) != "int")
                {
                    throw new Exception($"Map's size node type {mapSize.Type} doesn't match expected value 'int'");
                }
                if (mapSize.Name != "size")
                {
                    throw new Exception($"Map's size node name {mapSize.Name} doesn't match expected value 'size'");
                }

                TreeNodeDump pair = array.Children[1];
                if (pair.Children.Count != 2)
                {
                    throw new Exception($"Map's value node has {array.Children.Count} children but expected 2");
                }
                if (pair.Type != "pair")
                {
                    throw new Exception($"Map's value node type {pair.Type} doesn't match expected value 'pair'");
                }
                if (pair.Name != "data")
                {
                    throw new Exception($"Map's value node name {pair.Name} doesn't match expected value 'data'");
                }

                TreeNodeDump key = pair.Children[0];
                if (key.Name != "first")
                {
                    throw new Exception($"Map's kvp-key node name {key.Name} doesn't match expected value 'first'");
                }
                TreeNodeDump value = pair.Children[1];
                if (value.Name != "second")
                {
                    throw new Exception($"Map's kvp-value node name {value.Name} doesn't match expected value 'second'");
                }

                return($"Dictionary<{ToOptimizedType(key)}, {ToOptimizedType(value)}>");
            }

            case "set":
            {
                if (children.Count != 1)
                {
                    throw new Exception($"Set has {children.Count} children but expected 1");
                }

                TreeNodeDump array = children[0];
                if (array.Children.Count != 2)
                {
                    throw new Exception($"Set's array node has {array.Children.Count} children but expected 2");
                }
                if (array.Type != "Array")
                {
                    throw new Exception($"Set's array node type {array.Name} doesn't match expected value 'Array'");
                }
                if (array.Name != "Array")
                {
                    throw new Exception($"Set's array node name {array.Name} doesn't match expected value 'Array'");
                }

                TreeNodeDump setSize = array.Children[0];
                if (ToOptimizedType(setSize) != "int")
                {
                    throw new Exception($"Set's size node type {setSize.Type} doesn't match expected value 'int'");
                }
                if (setSize.Name != "size")
                {
                    throw new Exception($"Set's size node name {setSize.Name} doesn't match expected value 'size'");
                }

                TreeNodeDump setValue = array.Children[1];
                if (setValue.Name != "data")
                {
                    throw new Exception($"Set's value node name {setValue.Name} doesn't match expected value 'data'");
                }

                return($"HashSet<{ToOptimizedType(setValue)}>");
            }

            case "string":
            {
                if (children.Count != 1)
                {
                    throw new Exception($"String has {children.Count} children but expected 1");
                }

                TreeNodeDump array = children[0];
                if (array.Children.Count != 2)
                {
                    return(type);
                }
                if (array.Type != "Array")
                {
                    throw new Exception($"String's array node type {array.Name} doesn't match expected value 'Array'");
                }
                if (array.Name != "Array")
                {
                    throw new Exception($"String's array node name {array.Name} doesn't match expected value 'Array'");
                }

                TreeNodeDump stringSize = array.Children[0];
                if (ToOptimizedType(stringSize) != "int")
                {
                    throw new Exception($"String's size node type {stringSize.Type} doesn't match expected value 'int'");
                }
                if (stringSize.Name != "size")
                {
                    throw new Exception($"String's size node name {stringSize.Name} doesn't match expected value 'size'");
                }

                TreeNodeDump stringValue = array.Children[1];
                if (stringValue.Type != "char")
                {
                    throw new Exception($"String's value node type {stringValue.Type} doesn't match expected value 'char'");
                }
                if (stringValue.Name != "data")
                {
                    throw new Exception($"String's value node name {stringValue.Name} doesn't match expected value 'data'");
                }

                return("string");
            }

            case "pair":
            {
                if (children.Count != 2)
                {
                    throw new Exception($"Pair has {children.Count} children but expected 2");
                }

                TreeNodeDump first = children[0];
                if (first.Name != "first")
                {
                    throw new Exception($"Pair's first child name {children[0].Name} doesn't match expected value 'first'");
                }
                TreeNodeDump second = children[1];
                if (second.Name != "second")
                {
                    throw new Exception($"Pair's first child name {children[0].Name} doesn't match expected value 'second'");
                }
                return($"KeyValuePair<{ToOptimizedType(first)}, {ToOptimizedType(second)}>");
            }

            case "TypelessData":
            {
                if (children.Count != 2)
                {
                    throw new Exception($"Typeless data has {children.Count} children but expected 2");
                }

                TreeNodeDump dataSize = children[0];
                if (ToOptimizedType(dataSize) != "int")
                {
                    throw new Exception($"Typeless data's size node type {dataSize.Type} doesn't match expected value 'int'");
                }
                if (dataSize.Name != "size")
                {
                    throw new Exception($"Typeless data's size node name {dataSize.Name} doesn't match expected value 'size'");
                }

                TreeNodeDump dataValue = children[1];
                if (ToOptimizedType(dataValue) != "byte")
                {
                    throw new Exception($"String's value node type {dataValue.Type} doesn't match expected value 'byte'");
                }
                if (dataValue.Name != "data")
                {
                    throw new Exception($"String's value node name {dataValue.Name} doesn't match expected value 'data'");
                }
                return($"byte[]");
            }

            default:
                return(type);
            }
        }
예제 #11
0
 public TreeNodeDiff(TreeNodeDump left, TreeNodeDump right) :
     this(left, right, false)
 {
 }
예제 #12
0
 private static bool IsNodeSame(TreeNodeDump left, TreeNodeDump right)
 {
     return(left.Name == right.Name);
 }