Beispiel #1
0
        public UtfBuilder(DuplicatableStream stream, Endianness endian = Endianness.BigEndian)
        {
            long utfHeaderOffset = stream.Position;
            uint utfMagic        = stream.ReadUInt32(Endianness.LittleEndian);

            if (utfMagic != 0x46545540)
            {
                throw new Exception("wrong UTF magic");
            }

            uint size = stream.ReadUInt32(endian);             // size of the whole UTF chunk minus the magic and this value itself

            // offsets are relative to here
            long offset = stream.Position;

            uint   rowsLocation                   = stream.ReadUInt32(endian);
            uint   stringTableLocation            = stream.ReadUInt32(endian);
            uint   dataTableLocation              = stream.ReadUInt32(endian);
            uint   tableNameLocationInStringTable = stream.ReadUInt32(endian);
            ushort colcount  = stream.ReadUInt16(endian);
            ushort rowwidth  = stream.ReadUInt16(endian);
            uint   rowcount  = stream.ReadUInt32(endian);
            string tableName = stream.ReadUTF8NulltermFromLocationAndReset(offset + stringTableLocation + tableNameLocationInStringTable);

            // utf_tab calls this the 'schema'
            List <ColumnData> columns = new List <ColumnData>(colcount);

            for (int i = 0; i < colcount; ++i)
            {
                ColumnData col = new ColumnData();
                col.Type = stream.ReadUInt8();
                uint stroffset = stream.ReadUInt32(endian);
                col.Name = stream.ReadUTF8NulltermFromLocationAndReset(offset + stringTableLocation + stroffset);

                if ((col.Type & utf_tab_sharp.UtfTab.COLUMN_STORAGE_MASK) == utf_tab_sharp.UtfTab.COLUMN_STORAGE_CONSTANT)
                {
                    switch (col.Type & utf_tab_sharp.UtfTab.COLUMN_TYPE_MASK)
                    {
                    case utf_tab_sharp.UtfTab.COLUMN_TYPE_STRING:
                        uint datastroffset = stream.ReadUInt32(endian);
                        col.Data = stream.ReadUTF8NulltermFromLocationAndReset(offset + stringTableLocation + datastroffset);
                        break;

                    case utf_tab_sharp.UtfTab.COLUMN_TYPE_8BYTE:
                        col.Data = stream.ReadUInt64(endian);
                        break;

                    case utf_tab_sharp.UtfTab.COLUMN_TYPE_DATA:
                        uint dataOffset = stream.ReadUInt32(endian);
                        uint dataSize   = stream.ReadUInt32(endian);
                        col.Data = stream.ReadBytesFromLocationAndReset(offset + dataTableLocation + dataOffset, dataSize);
                        break;

                    case utf_tab_sharp.UtfTab.COLUMN_TYPE_FLOAT:
                        col.Data = stream.ReadUInt32(endian).UIntToFloat();
                        break;

                    case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE2:
                    case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE:
                        col.Data = stream.ReadUInt32(endian);
                        break;

                    case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE2:
                    case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE:
                        col.Data = stream.ReadUInt16(endian);
                        break;

                    case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE2:
                    case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE:
                        col.Data = stream.ReadUInt8();
                        break;

                    default:
                        throw new Exception("unknown type for constant");
                    }
                }

                columns.Add(col);
            }

            List <RowData> rows = new List <RowData>((int)rowcount);

            for (long i = 0; i < rowcount; ++i)
            {
                stream.Position = offset + rowsLocation + (i * rowwidth);
                RowData row = new RowData();
                row.Cells = new List <CellData>();
                for (int j = 0; j < colcount; ++j)
                {
                    CellData cell = new CellData();
                    byte     type = columns[j].Type;
                    switch ((type & utf_tab_sharp.UtfTab.COLUMN_STORAGE_MASK))
                    {
                    case utf_tab_sharp.UtfTab.COLUMN_STORAGE_PERROW:
                        switch (type & utf_tab_sharp.UtfTab.COLUMN_TYPE_MASK)
                        {
                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_STRING:
                            uint datastroffset = stream.ReadUInt32(endian);
                            cell.Data = stream.ReadUTF8NulltermFromLocationAndReset(offset + stringTableLocation + datastroffset);
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_8BYTE:
                            cell.Data = stream.ReadUInt64(endian);
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_DATA:
                            uint dataOffset = stream.ReadUInt32(endian);
                            uint dataSize   = stream.ReadUInt32(endian);
                            cell.Data = stream.ReadBytesFromLocationAndReset(offset + dataTableLocation + dataOffset, dataSize);
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_FLOAT:
                            cell.Data = stream.ReadUInt32(endian).UIntToFloat();
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE2:
                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE:
                            cell.Data = stream.ReadUInt32(endian);
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE2:
                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE:
                            cell.Data = stream.ReadUInt16(endian);
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE2:
                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE:
                            cell.Data = stream.ReadUInt8();
                            break;

                        default:
                            throw new Exception("unknown type for value");
                        }
                        break;

                    case utf_tab_sharp.UtfTab.COLUMN_STORAGE_CONSTANT:
                        cell.Data = columns[j].Data;
                        break;

                    case utf_tab_sharp.UtfTab.COLUMN_STORAGE_ZERO:
                        switch (type & utf_tab_sharp.UtfTab.COLUMN_TYPE_MASK)
                        {
                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_STRING:
                            cell.Data = "";
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_8BYTE:
                            cell.Data = (ulong)0;
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_DATA:
                            cell.Data = new byte[0];
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_FLOAT:
                            cell.Data = 0.0f;
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE2:
                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE:
                            cell.Data = (uint)0;
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE2:
                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE:
                            cell.Data = (ushort)0;
                            break;

                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE2:
                        case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE:
                            cell.Data = (byte)0;
                            break;

                        default:
                            throw new Exception("unknown type for value");
                        }
                        break;

                    default:
                        throw new Exception("unknown storage for value");
                    }
                    row.Cells.Add(cell);
                }
                rows.Add(row);
            }

            Name    = tableName;
            Columns = columns;
            Rows    = rows;

            stream.Position = utfHeaderOffset + ((long)8) + ((long)size);

            return;
        }