public static void DissectNodes(IEnumerable <BaseHexNode> nodes, IProcessReader reader, MemoryBuffer memory)
        {
            Contract.Requires(nodes != null);
            Contract.Requires(Contract.ForAll(nodes, n => n != null));
            Contract.Requires(memory != null);

            foreach (var node in nodes)
            {
                if (GuessNode(node, reader, memory, out var guessedNode))
                {
                    node.GetParentContainer()?.ReplaceChildNode(node, guessedNode);
                }
            }
        }
        public static bool GuessNode(BaseHexNode node, IProcessReader reader, MemoryBuffer memory, out BaseNode guessedNode)
        {
            Contract.Requires(node != null);
            Contract.Requires(memory != null);

            guessedNode = null;

            var offset         = node.Offset;
            var is4ByteAligned = offset % 4 == 0;
            var is8ByteAligned = offset % 8 == 0;

            // The node is not aligned, skip it.
            if (!is4ByteAligned)
            {
                return(false);
            }

            var data64 = memory.ReadObject <UInt64FloatDoubleData>(offset);
            var data32 = memory.ReadObject <UInt32FloatData>(offset);

            var raw = memory.ReadBytes(offset, node.MemorySize);

            if (raw.InterpretAsSingleByteCharacter().IsLikelyPrintableData())
            {
                guessedNode = new Utf8TextNode();

                return(true);
            }
            if (raw.InterpretAsDoubleByteCharacter().IsLikelyPrintableData())
            {
                guessedNode = new Utf16TextNode();

                return(true);
            }

#if RECLASSNET64
            if (is8ByteAligned)
            {
                if (GuessPointerNode(data64.IntPtr, reader, out guessedNode))
                {
                    return(true);
                }
            }
#else
            if (GuessPointerNode(data32.IntPtr, reader, out guessedNode))
            {
                return(true);
            }
#endif

            // 0 could be anything.
            if (data32.IntValue != 0)
            {
                // If the data represents a reasonable range, it could be a float.
                if (-999999.0f <= data32.FloatValue && data32.FloatValue <= 999999.0f && !data32.FloatValue.IsNearlyEqual(0.0f, 0.001f))
                {
                    guessedNode = new FloatNode();

                    return(true);
                }

                if (-999999 <= data32.IntValue && data32.IntValue <= 999999)
                {
                    guessedNode = new Int32Node();

                    return(true);
                }
            }

            if (is8ByteAligned)
            {
                if (data64.LongValue != 0)
                {
                    // If the data represents a reasonable range, it could be a double.
                    if (-999999.0 <= data64.DoubleValue && data64.DoubleValue <= 999999.0 && !data64.DoubleValue.IsNearlyEqual(0.0, 0.001))
                    {
                        guessedNode = new DoubleNode();

                        return(true);
                    }
                }
            }

            return(false);
        }
        public static Type GuessType(BaseHexNode node, MemoryBuffer memory)
        {
            Contract.Requires(node != null);
            Contract.Requires(memory != null);

            var offset         = node.Offset.ToInt32();
            var is4ByteAligned = offset % 4 == 0;
            var is8ByteAligned = offset % 8 == 0;

            // The node is not aligned, skip it.
            if (!is4ByteAligned)
            {
                return(null);
            }

            var data64 = memory.ReadObject <UInt64FloatDoubleData>(offset);
            var data32 = memory.ReadObject <UInt32FloatData>(offset);

            var raw = memory.ReadBytes(offset, node.MemorySize);

            if (raw.InterpretAsUtf8().IsLikelyPrintableData() >= 0.75f)
            {
                return(typeof(Utf8TextNode));
            }
            if (raw.InterpretAsUtf16().IsLikelyPrintableData() >= 0.75f)
            {
                return(typeof(Utf16TextNode));
            }

            if (is8ByteAligned)
            {
#if RECLASSNET64
                var pointerType = GuessPointerType(data64.IntPtr, memory);
                if (pointerType != null)
                {
                    return(pointerType);
                }
#endif
            }

            {
#if RECLASSNET32
                var pointerType = GuessPointerType(data32.IntPtr, memory);
                if (pointerType != null)
                {
                    return(pointerType);
                }
#endif

                // 0 could be anything.
                if (data32.IntValue != 0)
                {
                    // If the data represents a reasonable range, it could be a float.
                    if (-99999.0f <= data32.FloatValue && data32.FloatValue <= 99999.0f && !data32.FloatValue.IsNearlyEqual(0.0f, 0.001f))
                    {
                        return(typeof(FloatNode));
                    }

                    if (-99999 <= data32.IntValue && data32.IntValue <= 99999)
                    {
                        return(typeof(Int32Node));
                    }
                }
            }

            if (is8ByteAligned)
            {
                if (data64.LongValue != 0)
                {
                    // If the data represents a reasonable range, it could be a double.
                    if (-99999.0 <= data64.DoubleValue && data64.DoubleValue <= 99999.0 && !data64.DoubleValue.IsNearlyEqual(0.0, 0.001))
                    {
                        return(typeof(DoubleNode));
                    }
                }
            }

            return(null);
        }