예제 #1
0
        /// <summary>
        ///     Initialize with a span buffer
        /// </summary>
        /// <param name="buffer"></param>
        public XL19(Span <byte> buffer)
        {
            var header = MemoryMarshal.Read <XLHeader>(buffer);

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

            var offset = (int)header.TableOffset;
            var sz     = SizeHelper.SizeOf <XLHeader>();

            Types = MemoryMarshal.Cast <byte, XLType>(buffer.Slice(sz, header.Types)).ToArray();
            for (var i = 0; i < header.Sets; i++)
            {
                List <object?> data      = new List <object?>();
                var            locOffset = 0;
                var            slice     = buffer.Slice(offset);
                foreach (var type in Types)
                {
                    switch (type)
                    {
                    case XLType.StringPointer:
                    {
                        data.Add(buffer.Slice(header.TableOffset + SpanHelper.ReadLittleInt(slice, ref locOffset)).ReadStringNonNull());
                        break;
                    }

                    case XLType.Int32:
                    {
                        data.Add(SpanHelper.ReadLittleInt(slice, ref locOffset));
                        break;
                    }

                    case XLType.Int16:
                    {
                        data.Add(SpanHelper.ReadLittleShort(slice, ref locOffset));
                        break;
                    }

                    case XLType.Int8:
                    {
                        data.Add(SpanHelper.ReadSByte(slice, ref locOffset));
                        break;
                    }

                    case XLType.UInt32:
                    {
                        data.Add(SpanHelper.ReadLittleUInt(slice, ref locOffset));
                        break;
                    }

                    case XLType.UInt16:
                    {
                        data.Add(SpanHelper.ReadLittleUShort(slice, ref locOffset));
                        break;
                    }

                    case XLType.UInt8:
                    {
                        data.Add(SpanHelper.ReadByte(slice, ref locOffset));
                        break;
                    }

                    case XLType.Single:
                    {
                        data.Add(SpanHelper.ReadLittleSingle(slice, ref locOffset));
                        break;
                    }

                    case XLType.NOP:
                        data.Add(null);
                        break;

                    default:
                        throw new NotImplementedException($"opcode {type:G}");
                    }
                }

                if (locOffset != header.Width)
                {
                    Logger.Warn("XL", "Offset misaligned!");
                }
                Entries.Add(data);
                offset += header.Width;
            }
        }
예제 #2
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;
            }
        }
예제 #3
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);
        }