コード例 #1
0
        public void Long()
        {
            var real_bytes = BitConverter.GetBytes(long.MaxValue);

            Assert.AreEqual(long.MaxValue, PointerCastHelper.BytesToLong(real_bytes, 0), "No se convirtió el puntero correctamente");
            Assert.AreEqual(BitConverter.ToInt64(PointerCastHelper.LongToBytes(long.MaxValue), 0), long.MaxValue, "No se reconvirtieron los bytes correctamente");
        }
コード例 #2
0
        /// <summary>
        /// Devuelve el objeto serializado sin incluir la cabecera con el tamaño y el estado de borrado.
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="graph"></param>
        /// <returns></returns>
        public static byte[] Serialize <TModel>(TModel graph)
        {
            if (!typeof(TModel).IsInterface)
            {
                throw new InvalidOperationException("El modelo <TModel> debe ser una interfaz");
            }

            MemoryStream result = new MemoryStream();

            var props = GetPropertiesOrderForInterface(typeof(TModel));

            //Obtenemos las propiedades en el orden de serialización y las serializamos en result
            foreach (var prop in props)
            {
                string method = PointerCastHelper.GetTypeToByteMethod(prop.PropertyType);

                byte[] value = (byte[])typeof(PointerCastHelper)
                               .GetMethod(method, new Type[] { prop.PropertyType })
                               .Invoke(null, new object[] { prop.GetValue(graph) });

                result.Write(value, 0, value.Length);
            }

            return(result.ToArray());
        }
コード例 #3
0
        public void GetStringOffsetAtIndex()
        {
            //cargamos 3 strings en un array
            MemoryStream ms = new MemoryStream();

            byte[] bytes = PointerCastHelper.StringToBytes("texto 1");
            ms.Write(bytes, 0, bytes.Length);

            bytes = PointerCastHelper.StringToBytes("texto 2");
            ms.Write(bytes, 0, bytes.Length);

            bytes = PointerCastHelper.StringToBytes("texto 3");
            ms.Write(bytes, 0, bytes.Length);

            byte[] data = ms.ToArray();

            long offset2 = PointerCastHelper.GetStringOffsetAtIndex(data, 0, 1);
            long offset3 = PointerCastHelper.GetStringOffsetAtIndex(data, 0, 2);

            Assert.AreEqual(15, offset2, "El offset del segundo string debería ser 16");

            Assert.AreEqual("texto 1", PointerCastHelper.BytesToString(data, 0), "No coinciden los textos");
            Assert.AreEqual("texto 2", PointerCastHelper.BytesToString(data, offset2), "No coinciden los textos");
            Assert.AreEqual("texto 3", PointerCastHelper.BytesToString(data, offset3), "No coinciden los textos");
        }
コード例 #4
0
        public void String()
        {
            string test = "String de prueba para el test";

            string result = PointerCastHelper.BytesToString(
                PointerCastHelper.StringToBytes(test), 0);

            Assert.AreEqual(test, result, "Los textos no coinciden");
        }
コード例 #5
0
        public static void DeSerializeHeader(byte[] data, long offset, out int length, out bool deleted)
        {
            /*Header:
             * byte[4] longitud <- delante para mantener el alineamiento de la memoria.
             * byte flags:
             *          0x01 = Borrado
             */

            length  = PointerCastHelper.BytesToInt(data, offset);
            deleted = (data[offset + 4] & 0x01) == 0x01;
        }
コード例 #6
0
        public void Short()
        {
            var real_bytes = BitConverter.GetBytes(short.MaxValue);

            Assert.AreEqual(short.MaxValue, PointerCastHelper.BytesToShort(real_bytes, 0), "No se convirtió el puntero correctamente");

            for (int n = 0; n < 2; n++)
            {
                Assert.AreEqual(real_bytes[n], PointerCastHelper.ShortToBytes(short.MaxValue)[n], "No se hizo la conversión correctamente");
            }
        }
コード例 #7
0
        public void Double()
        {
            var real_bytes = BitConverter.GetBytes(12345678.23);

            Assert.AreEqual(12345678.23, PointerCastHelper.BytesToDouble(real_bytes, 0), "No se convirtió el puntero correctamente");

            for (int n = 0; n < 8; n++)
            {
                Assert.AreEqual(real_bytes[n], PointerCastHelper.DoubleToBytes(12345678.23)[n], "No se hizo la conversión correctamente");
            }
        }
コード例 #8
0
        public void Int()
        {
            var real_bytes = BitConverter.GetBytes(12345678);

            Assert.AreEqual(12345678, PointerCastHelper.BytesToInt(real_bytes, 0), "No se convirtió el puntero correctamente");

            Assert.AreEqual(real_bytes[0], PointerCastHelper.IntToBytes(12345678)[0], "No se convirtió a un array de bytes correctamente");
            Assert.AreEqual(real_bytes[1], PointerCastHelper.IntToBytes(12345678)[1], "No se convirtió a un array de bytes correctamente");
            Assert.AreEqual(real_bytes[2], PointerCastHelper.IntToBytes(12345678)[2], "No se convirtió a un array de bytes correctamente");
            Assert.AreEqual(real_bytes[3], PointerCastHelper.IntToBytes(12345678)[3], "No se convirtió a un array de bytes correctamente");
        }
コード例 #9
0
        public bool MoveNext()
        {
            if (data.Length == 0)
            {
                return(false);
            }

            if (current_offset == -1)
            {
                current_offset = 0;

                //todo: optimize! importante que esto sea óptimo dado que es el iterador principal
                //movemos el cursor hacia adelante el largo del registro.
                bool deleted;
                int  length;
                SerializationHelper
                .DeSerializeHeader(data, current_offset, out length, out deleted);

                if (deleted)
                {
                    return(MoveNext());
                }

                if (data.Length > 0)
                {
                    return(true);
                }
            }
            else
            {
                //todo: optimize! importante que esto sea óptimo dado que es el iterador principal
                int length = PointerCastHelper.BytesToInt(data, current_offset);
                //movemos el cursor hacia adelante el largo del registro.
                current_offset += length + Constants.RECORD_HEADER_SIZE;

                if (current_offset >= data.Length)
                {
                    return(false);
                }

                bool deleted = (data[current_offset + 5] & 0x01) == 0x01;
                if (deleted)
                {
                    return(MoveNext());
                }

                if (data.Length > current_offset)//???
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #10
0
        public static byte[] SerializeHeader(int record_length, bool deleted = false)
        {
            byte[] header = new byte[5];
            PointerCastHelper.IntToBytes(record_length).CopyTo(header, 0);

            if (deleted)
            {
                header[4] = 0x01;
            }

            return(header);
        }
コード例 #11
0
        public static IEnumerable <System.Reflection.PropertyInfo> GetPropertiesOrderForInterface(Type TModel)
        {
            if (!TModel.IsInterface)
            {
                throw new InvalidOperationException("El modelo <TModel> debe ser una interfaz");
            }

            //obtenemos las propiedades del tipo de interfaz del modelo
            var properties = TModel
                             .GetProperties()
                             .OrderByDescending(x => PointerCastHelper.TypeSizeInMemory(x.PropertyType));//así quedan las de tamaño variable al final.

            return(properties);
        }
コード例 #12
0
        public void Serialize()
        {
            var model = new testmodel()
            {
                value  = 1,
                value3 = 2D,
                text1  = "texto 1",
                text2  = "otro texto de prueba"
            };

            byte[] serialization = SerializationHelper.Serialize <ITestModel>(model);

            //según la ordenación, lo primero debería ser el campo más grande, el double, después el entero y los strings.

            Assert.AreEqual(1, PointerCastHelper.BytesToInt(serialization, 8));
            Assert.AreEqual(2D, PointerCastHelper.BytesToDouble(serialization, 0));
            Assert.AreEqual("texto 1", PointerCastHelper.GetStringAtOffset(serialization, 12, 0));
            Assert.AreEqual("otro texto de prueba", PointerCastHelper.GetStringAtOffset(serialization, 12, 1));
        }
コード例 #13
0
        private static Type BuildWrapperType(Type interface_type)
        {
            //si anteriormente se había creado un tipo para esta interfaz lo devolvemos.
            if (generated_types_cache.ContainsKey(interface_type))
            {
                return(generated_types_cache[interface_type]);
            }

            string type_name =
                interface_type.FullName.Replace('.', '_') +
                Constants.WRAPPER_TYPE_NAME_SUFIX;

            //definimos la nueva classe wrapper.
            TypeBuilder type_builder = module_builder.DefineType(type_name,
                                                                 TypeAttributes.Class |
                                                                 TypeAttributes.Public |
                                                                 TypeAttributes.AutoClass |
                                                                 TypeAttributes.AnsiClass,
                                                                 null,
                                                                 Type.EmptyTypes);

            //Añadimos la implementación de la interfaz del modelo.
            type_builder.AddInterfaceImplementation(interface_type);

            //creamos una variable estática en cla clase que contendrá
            //un puntero al array de bytes del origen de datos.
            FieldBuilder data_field = type_builder
                                      .DefineField("data", typeof(Byte[]),
                                                   FieldAttributes.Public | FieldAttributes.Static);

            //creamos otra variable para almacenar el offset del registro actual
            FieldBuilder offset_field = type_builder
                                        .DefineField("offset", typeof(long), FieldAttributes.Public);

            //obtenemos las propiedades del tipo de interfaz del modelo
            var properties = SerializationHelper.GetPropertiesOrderForInterface(interface_type);

            //offset de la propiedad dentro del conjunto de bytes del registro.
            int prop_offset         = 0;
            int first_string_offset = -1;
            int string_index        = 0;

            //implementamos las propiedades
            foreach (var prop in properties)
            {
                //método de transformación del array de bytes al tipo de la propiedad.
                string cast_method_name = PointerCastHelper.GetByteToTypeMethod(prop.PropertyType);

                PropertyBuilder prop_builder = type_builder
                                               .DefineProperty(prop.Name,
                                                               PropertyAttributes.HasDefault,
                                                               prop.PropertyType,
                                                               Type.EmptyTypes);

                //definimos el método get
                MethodBuilder pGet = type_builder.DefineMethod("get_" + prop.Name,
                                                               MethodAttributes.Virtual |
                                                               MethodAttributes.Public |
                                                               MethodAttributes.SpecialName |
                                                               MethodAttributes.HideBySig,
                                                               prop.PropertyType, Type.EmptyTypes);

                var getIl = pGet.GetILGenerator();

                //emitimos el código que convierte el array de bytes encontrado en el
                //offset de la variable del modelo a un puntero del tipo de retorno.
                if (prop.PropertyType == typeof(string))
                {
                    if (first_string_offset == -1)
                    {
                        first_string_offset = prop_offset;
                    }

                    //llamámos al método que nos dá el offset de este índice de string. GetStringOffsetAtIndex
                    getIl.Emit(OpCodes.Ldsfld, data_field);
                    getIl.Emit(OpCodes.Ldarg_0);
                    //sumamos el offset del primer campo con el del registro
                    getIl.Emit(OpCodes.Ldfld, offset_field);
                    getIl.Emit(OpCodes.Ldc_I4, prop_offset);
                    getIl.Emit(OpCodes.Conv_I8);
                    getIl.Emit(OpCodes.Add);
                    //añadimos el indice del string que estamos cargando.
                    getIl.Emit(OpCodes.Ldc_I4, string_index++);
                    //obtenemos el offset del string.
                    getIl.Emit(OpCodes.Call, typeof(PointerCastHelper).GetMethod("GetStringAtOffset"));
                    getIl.Emit(OpCodes.Ret);
                }
                else
                {
                    getIl.Emit(OpCodes.Nop);
                    getIl.Emit(OpCodes.Ldsfld, data_field);
                    getIl.Emit(OpCodes.Ldarg_0);
                    getIl.Emit(OpCodes.Ldfld, offset_field);
                    getIl.Emit(OpCodes.Ldc_I4, prop_offset);
                    getIl.Emit(OpCodes.Conv_I8);
                    getIl.Emit(OpCodes.Add);
                    getIl.Emit(OpCodes.Call, typeof(PointerCastHelper).GetMethod(PointerCastHelper.GetByteToTypeMethod(prop.PropertyType)));
                    getIl.Emit(OpCodes.Ret);
                    prop_offset += PointerCastHelper.TypeSizeInMemory(prop.PropertyType);
                }

                prop_builder.SetGetMethod(pGet);

                type_builder.DefineMethodOverride(pGet, interface_type.GetMethod("get_" + prop.Name));
            }


            //Añadimos el nuevo tipo a la caché de creación.
            Type created = type_builder.CreateType();

            generated_types_cache.Add(interface_type, created);
            return(created);
        }