Пример #1
0
        /// <summary>
        ///     Initialize with a span buffer
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="t"></param>
        public XL20(Span <byte> buffer, Type t)
        {
            var header = MemoryMarshal.Read <XLHeader>(buffer);

            if (header.Magic != ((uint)DataType.XL & 0xFFFF) && header.Version != 0x14)
            {
                throw new InvalidOperationException("Not an XL stream");
            }
            UnderlyingType = t;

            var offset     = (int)header.TableOffset;
            var properties = t.GetProperties();

            for (var i = 0; i < header.FileSize; i++)
            {
                var instance    = Activator.CreateInstance(t);
                var localOffset = 0;
                var slice       = buffer.Slice(offset);
                foreach (var property in properties)
                {
                    var    type = property.PropertyType;
                    object?value;
                    switch (type.FullName)
                    {
                    case "System.Int64":
                        value = SpanHelper.ReadLittleLong(slice, ref localOffset);
                        break;

                    case "System.Int32":
                        value = SpanHelper.ReadLittleInt(slice, ref localOffset);
                        break;

                    case "System.Int16":
                        value = SpanHelper.ReadLittleShort(slice, ref localOffset);
                        break;

                    case "System.UInt64":
                        value = SpanHelper.ReadLittleULong(slice, ref localOffset);
                        break;

                    case "System.UInt32":
                        value = SpanHelper.ReadLittleUInt(slice, ref localOffset);
                        break;

                    case "System.UInt16":
                        value = SpanHelper.ReadLittleUShort(slice, ref localOffset);
                        break;

                    case "System.Int8":
                    case "System.SByte":
                        value = SpanHelper.ReadSByte(slice, ref localOffset);
                        break;

                    case "System.UInt8":
                    case "System.Byte":
                        value = SpanHelper.ReadByte(slice, ref localOffset);
                        break;

                    case "System.Single":
                        value = SpanHelper.ReadLittleSingle(slice, ref localOffset);
                        break;

                    case "System.Double":
                        value = SpanHelper.ReadLittleDouble(slice, ref localOffset);
                        break;

                    case "System.Decimal":
                        value = SpanHelper.ReadLittleDecimal(slice, ref localOffset);
                        break;

                    case "System.Boolean":
                        value = SpanHelper.ReadByte(slice, ref localOffset) == 1;
                        break;

                    case "System.String":
                    {
                        var stringSize = property.GetCustomAttribute <StringLengthAttribute>();
                        var size       = stringSize?.MaximumLength ?? SpanHelper.ReadLittleInt(slice, ref localOffset);
                        value = size > 0 ? Encoding.UTF8.GetString(slice.Slice(localOffset, size)) : null;
                        if (stringSize != null && value is string stringValue)
                        {
                            value = stringValue.TrimEnd('\u0000');
                        }
                        localOffset += size;
                        break;
                    }

                    default:
                        throw new NotImplementedException(type.FullName);
                    }

                    property.SetValue(instance, value);
                }

                Entries.Add(instance);
                offset += localOffset;
            }
        }
Пример #2
0
        /// <summary>
        ///     Cast all entries to the specified struct type.
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public List <object?> Cast(Type t)
        {
            var entries    = new List <object?>();
            var properties = t.GetProperties();
            var count      = Math.Min(Header.FieldCount, properties.Length);

            foreach (var buffer in Entries)
            {
                var slice       = buffer.Span;
                var instance    = Activator.CreateInstance(t);
                var localOffset = 0;
                for (var index = 0; index < count; index++)
                {
                    var    property = properties[index];
                    var    type     = property.PropertyType;
                    object?value;
                    switch (type.FullName)
                    {
                    case "System.Int64":
                        value = SpanHelper.ReadLittleLong(slice, ref localOffset);
                        break;

                    case "System.Int32":
                        value = SpanHelper.ReadLittleInt(slice, ref localOffset);
                        break;

                    case "System.Int16":
                        value = SpanHelper.ReadLittleShort(slice, ref localOffset);
                        break;

                    case "System.UInt64":
                        value = SpanHelper.ReadLittleULong(slice, ref localOffset);
                        break;

                    case "System.UInt32":
                        value = SpanHelper.ReadLittleUInt(slice, ref localOffset);
                        break;

                    case "System.UInt16":
                        value = SpanHelper.ReadLittleUShort(slice, ref localOffset);
                        break;

                    case "System.Int8":
                    case "System.SByte":
                        value = SpanHelper.ReadSByte(slice, ref localOffset);
                        break;

                    case "System.UInt8":
                    case "System.Byte":
                        value = SpanHelper.ReadByte(slice, ref localOffset);
                        break;

                    case "System.Single":
                        value = SpanHelper.ReadLittleSingle(slice, ref localOffset);
                        break;

                    case "System.Double":
                        value = SpanHelper.ReadLittleDouble(slice, ref localOffset);
                        break;

                    case "System.Boolean":
                        value = SpanHelper.ReadByte(slice, ref localOffset) == 1;
                        break;

                    case "System.String":
                    {
                        var offset = SpanHelper.ReadLittleInt(slice, ref localOffset);
                        value = null;
                        var resolvedSize = DynamicData.Length - SizeHelper.SizeOf <ECBStringHeader>();
                        if (offset >= 0 && resolvedSize >= 0 && offset < resolvedSize)
                        {
                            var stringHeader = MemoryMarshal.Read <ECBStringHeader>(DynamicData.Span.Slice(offset));
                            Logger.Assert(stringHeader.CharSet == ECBCharSet.UTF8, "CharSet == ECBCharSet.UTF8");
                            if (stringHeader.Size > 1)
                            {
                                value = Encoding.UTF8.GetString(DynamicData.Span.Slice(offset + SizeHelper.SizeOf <ECBStringHeader>(), stringHeader.Size - 1));
                            }
                        }

                        break;
                    }

                    default:
                        throw new NotImplementedException(type.FullName);
                    }

                    property.SetValue(instance, value);
                }

                entries.Add(instance);
            }

            return(entries);
        }