Beispiel #1
0
        public void ParseObject(object instance, REDBinaryReader red)
        {
            // Each object is prefixed with a zero byte header.
            var b = red.ReadByte();

            if (b != 0)
            {
                throw new FormatException($"Invalid object null header: {b}");
            }

            // Keep looping until the 2 byte null termintator is reached.
            while (true)
            {
                var name = red.ReadCName();
                if (CName.IsNullOrEmpty(name))
                {
                    // 2 byte null terminator instead of the next name id indicates the end of the object.
                    break;
                }
                var type = red.ReadCName();

                var start = red.BaseStream.Position;
                var size  = red.ReadUInt32();
                // Size value includes the size of the uint size value itself (+ 4).
                if (size < sizeof(uint))
                {
                    throw new FormatException($"Invalid object size: {size}");
                }

                // Check to see if the current class contains a property with the name and type read.
                var field = REDReflection.GetREDField(instance.GetType(), name, type);
                if (field == null)
                {
                    throw new FormatException($"Property '{name}' : '{type}', not found in class {instance.GetType().Name}, Aborting!");
                }

                var value = ReadObject(field.FieldType, red);

                var diff = start.CompareTo(red.BaseStream.Position);
                if (diff != 0)
                {
                    throw new FormatException($"Property '{name}' : '{type}', read unknown size of bytes, aborting!");
                }

                field.SetValue(instance, value);
            }
        }
Beispiel #2
0
        public object ReadObject(Type type, REDBinaryReader red)
        {
            #region .NET Types
            //Enum must be checked first because enums will be mistaken for values with typecode.
            if (type.IsEnum)
            {
                return(red.ReadEnumerator(type));
            }

            // Handles types such as [7]Float or [4]Int32
            if (type.IsArray)
            {
                var arraySize = red.ReadUInt32();
                var arrayType = type.GetElementType();
                var array     = Array.CreateInstance(arrayType, arraySize);
                for (int i = 0; i < arraySize; i++)
                {
                    var value = ReadObject(arrayType, red);
                    array.SetValue(value, i);
                }
                return(array);
            }

            // Handles all commom types from the .NET framework.
            var tCode = Type.GetTypeCode(type);
            switch (tCode)
            {
            case TypeCode.Byte:     return(red.ReadByte());

            case TypeCode.UInt16:   return(red.ReadUInt16());

            case TypeCode.UInt32:   return(red.ReadUInt32());

            case TypeCode.UInt64:   return(red.ReadUInt64());

            case TypeCode.SByte:    return(red.ReadSByte());

            case TypeCode.Int16:    return(red.ReadInt16());

            case TypeCode.Int32:    return(red.ReadInt32());

            case TypeCode.Int64:    return(red.ReadInt64());

            case TypeCode.Boolean:  return(red.ReadBoolean());

            case TypeCode.Single:   return(red.ReadSingle());

            case TypeCode.Double:   return(red.ReadDouble());

            case TypeCode.String:   return(red.ReadString());
            }
            #endregion

            #region Objects
            if (!type.IsAbstract)
            {
                var value = Activator.CreateInstance(type);
                if (value is IExportable obj)
                {
                }
                else
                {
                    ParseObject(value, red);
                }
                return(value);
            }
            #endregion

            throw new InvalidDataException();
        }
Beispiel #3
0
        public static object ReadProperty(Type type, REDBinaryReader r)
        {
            #region .NET Types
            //Enum must be checked first because enums will be mistaken for values with typecode.
            if (type.IsEnum)
            {
                return(r.ReadEnumerator(type));
            }

            if (type.IsArray)
            {
                //Handles cases of properties such as [7]Float or [5]Int32
                //Do not know how these are serialized yet.
                throw new NotImplementedException();
            }

            //Handles all commom types from the .NET framework.
            var tCode = Type.GetTypeCode(type);
            switch (tCode)
            {
            case TypeCode.Byte:     return(r.ReadByte());

            case TypeCode.UInt16:   return(r.ReadUInt16());

            case TypeCode.UInt32:   return(r.ReadUInt32());

            case TypeCode.UInt64:   return(r.ReadUInt64());

            case TypeCode.SByte:    return(r.ReadSByte());

            case TypeCode.Int16:    return(r.ReadInt16());

            case TypeCode.Int32:    return(r.ReadInt32());

            case TypeCode.Int64:    return(r.ReadInt64());

            case TypeCode.Boolean:  return(r.ReadBoolean());

            case TypeCode.Single:   return(r.ReadSingle());

            case TypeCode.Double:   return(r.ReadDouble());

            case TypeCode.String:   return(r.ReadString());
            }
            #endregion

            #region Objects
            if (!type.IsAbstract)
            {
                var value = Activator.CreateInstance(type);
                if (value is IExportable obj)
                {
                    //obj.ReadExport(stream, data);
                    return(obj);
                }
                else
                {
                    ReadObject(value, r);
                }
                return(value);
            }
            #endregion

            throw new InvalidDataException();
        }