private void InitializeUtfSchema(Stream sourceStream, Stream tableDataStream, long schemaOffset)
        {
            var header     = _utfHeader;
            var rows       = _rows;
            var baseOffset = _offset;

            for (uint i = 0; i < header.RowCount; i++)
            {
                var currentOffset = schemaOffset;
                var row           = new Dictionary <string, UtfField>();
                rows[i] = row;
                long currentRowOffset = 0;
                long currentRowBase   = header.PerRowDataOffset + header.RowSize * i;

                for (var j = 0; j < header.FieldCount; j++)
                {
                    var field = new UtfField {
                        Type = tableDataStream.PeekByte(currentOffset)
                    };

                    long nameOffset = tableDataStream.PeekInt32BE(currentOffset + 1);
                    field.Name = tableDataStream.PeekZeroEndedStringAsAscii(header.StringTableOffset + nameOffset);

                    var union = new NumericUnion();
                    var constrainedStorage = (ColumnStorage)(field.Type & (byte)ColumnStorage.Mask);
                    var constrainedType    = (ColumnType)(field.Type & (byte)ColumnType.Mask);
                    switch (constrainedStorage)
                    {
                    case ColumnStorage.Constant:
                    case ColumnStorage.Constant2:
                        var  constantOffset = currentOffset + 5;
                        long dataOffset;
                        switch (constrainedType)
                        {
                        case ColumnType.String:
                            dataOffset        = tableDataStream.PeekInt32BE(constantOffset);
                            field.StringValue = tableDataStream.PeekZeroEndedStringAsAscii(header.StringTableOffset + dataOffset);
                            currentOffset    += 4;
                            break;

                        case ColumnType.Int64:
                            union.S64      = tableDataStream.PeekInt64BE(constantOffset);
                            currentOffset += 8;
                            break;

                        case ColumnType.UInt64:
                            union.U64      = tableDataStream.PeekUInt64BE(constantOffset);
                            currentOffset += 8;
                            break;

                        case ColumnType.Data:
                            dataOffset = tableDataStream.PeekUInt32BE(constantOffset);
                            long dataSize = tableDataStream.PeekUInt32BE(constantOffset + 4);
                            field.Offset = baseOffset + header.ExtraDataOffset + dataOffset;
                            field.Size   = dataSize;
                            // don't think this is encrypted, need to check
                            field.DataValue = sourceStream.PeekBytes(field.Offset, (int)dataSize);
                            currentOffset  += 8;
                            break;

                        case ColumnType.Double:
                            union.R64      = tableDataStream.PeekDoubleBE(constantOffset);
                            currentOffset += 8;
                            break;

                        case ColumnType.Single:
                            union.R32      = tableDataStream.PeekSingleBE(constantOffset);
                            currentOffset += 4;
                            break;

                        case ColumnType.Int32:
                            union.S32      = tableDataStream.PeekInt32BE(constantOffset);
                            currentOffset += 4;
                            break;

                        case ColumnType.UInt32:
                            union.U32      = tableDataStream.PeekUInt32BE(constantOffset);
                            currentOffset += 4;
                            break;

                        case ColumnType.Int16:
                            union.S16      = tableDataStream.PeekInt16BE(constantOffset);
                            currentOffset += 2;
                            break;

                        case ColumnType.UInt16:
                            union.U16      = tableDataStream.PeekUInt16BE(constantOffset);
                            currentOffset += 2;
                            break;

                        case ColumnType.SByte:
                            union.S8       = tableDataStream.PeekSByte(constantOffset);
                            currentOffset += 1;
                            break;

                        case ColumnType.Byte:
                            union.U8       = tableDataStream.PeekByte(constantOffset);
                            currentOffset += 1;
                            break;

                        default:
                            throw new FormatException($"Unknown column type at offset: 0x{currentOffset:x8}");
                        }
                        break;

                    case ColumnStorage.PerRow:
                        // read the constant depending on the type
                        long rowDataOffset;
                        switch (constrainedType)
                        {
                        case ColumnType.String:
                            rowDataOffset     = tableDataStream.PeekUInt32BE(currentRowBase + currentRowOffset);
                            field.StringValue = tableDataStream.PeekZeroEndedStringAsAscii(header.StringTableOffset + rowDataOffset);
                            currentRowOffset += 4;
                            break;

                        case ColumnType.Int64:
                            union.S64         = tableDataStream.PeekInt64BE(currentRowBase + currentRowOffset);
                            currentRowOffset += 8;
                            break;

                        case ColumnType.UInt64:
                            union.U64         = tableDataStream.PeekUInt64BE(currentRowBase + currentRowOffset);
                            currentRowOffset += 8;
                            break;

                        case ColumnType.Data:
                            rowDataOffset = tableDataStream.PeekUInt32BE(currentRowBase + currentRowOffset);
                            long rowDataSize = tableDataStream.PeekUInt32BE(currentRowBase + currentRowOffset + 4);
                            field.Offset = baseOffset + header.ExtraDataOffset + rowDataOffset;
                            field.Size   = rowDataSize;
                            // don't think this is encrypted
                            field.DataValue   = sourceStream.PeekBytes(field.Offset, (int)rowDataSize);
                            currentRowOffset += 8;
                            break;

                        case ColumnType.Double:
                            union.R64         = tableDataStream.PeekDoubleBE(currentRowBase + currentRowOffset);
                            currentRowOffset += 8;
                            break;

                        case ColumnType.Single:
                            union.R32         = tableDataStream.PeekSingleBE(currentRowBase + currentRowOffset);
                            currentRowOffset += 4;
                            break;

                        case ColumnType.Int32:
                            union.S32         = tableDataStream.PeekInt32BE(currentRowBase + currentRowOffset);
                            currentRowOffset += 4;
                            break;

                        case ColumnType.UInt32:
                            union.U32         = tableDataStream.PeekUInt32BE(currentRowBase + currentRowOffset);
                            currentRowOffset += 4;
                            break;

                        case ColumnType.Int16:
                            union.S16         = tableDataStream.PeekInt16BE(currentRowBase + currentRowOffset);
                            currentRowOffset += 2;
                            break;

                        case ColumnType.UInt16:
                            union.U16         = tableDataStream.PeekUInt16BE(currentRowBase + currentRowOffset);
                            currentRowOffset += 2;
                            break;

                        case ColumnType.SByte:
                            union.S8          = tableDataStream.PeekSByte(currentRowBase + currentRowOffset);
                            currentRowOffset += 1;
                            break;

                        case ColumnType.Byte:
                            union.U8          = tableDataStream.PeekByte(currentRowBase + currentRowOffset);
                            currentRowOffset += 1;
                            break;

                        default:
                            throw new FormatException($"Unknown column type at offset: 0x{currentOffset:x8}");
                        }
                        field.ConstrainedType = (ColumnType)field.Type;
                        break;

                    default:
                        throw new FormatException($"Unknown column storage at offset: 0x{currentOffset:x8}");
                    }
                    // Union polyfill
                    field.ConstrainedType = constrainedType;
                    switch (constrainedType)
                    {
                    case ColumnType.String:
                    case ColumnType.Data:
                        break;

                    default:
                        field.NumericValue = union;
                        break;
                    }
                    row.Add(field.Name, field);
                    currentOffset += 5; //  sizeof(CriField.Type + CriField.NameOffset)
                }
            }
        }
Beispiel #2
0
        public void SetValue(object value)
        {
            ColumnType type;
            var        union = new NumericUnion();

            if (value is byte)
            {
                type     = ColumnType.Byte;
                union.U8 = (byte)value;
            }
            else if (value is sbyte)
            {
                type     = ColumnType.SByte;
                union.S8 = (sbyte)value;
            }
            else if (value is ushort)
            {
                type      = ColumnType.UInt16;
                union.U16 = (ushort)value;
            }
            else if (value is short)
            {
                type      = ColumnType.Int16;
                union.S16 = (short)value;
            }
            else if (value is uint)
            {
                type      = ColumnType.UInt32;
                union.U32 = (uint)value;
            }
            else if (value is int)
            {
                type      = ColumnType.Int32;
                union.S32 = (int)value;
            }
            else if (value is ulong)
            {
                type      = ColumnType.UInt64;
                union.U64 = (ulong)value;
            }
            else if (value is long)
            {
                type      = ColumnType.Int64;
                union.S64 = (long)value;
            }
            else if (value is string)
            {
                type        = ColumnType.String;
                StringValue = (string)value;
            }
            else if (value is byte[])
            {
                type      = ColumnType.Data;
                DataValue = (byte[])value;
            }
            else
            {
                throw new ArgumentException("Unsupported argument type.", nameof(value));
            }
            ConstrainedType = type;
            Type            = (byte)type;
            switch (type)
            {
            case ColumnType.String:
            case ColumnType.Data:
                break;

            default:
                NumericValue = union;
                break;
            }
        }