예제 #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;
            }
        }