Exemple #1
0
        private TRecord[] ReadTable(Stream peStream)
        {
            var columns = new ColumnIndexAttribute[ColumnCount];
            var fields  = new FieldInfo[ColumnCount];

            // map the fields to columns
            foreach (var fld in typeof(TRecord).GetFields())
            {
                var indexAttr = fld
                                .GetCustomAttributes(false)
                                .OfType <ColumnIndexAttribute>()
                                .FirstOrDefault();

                if (indexAttr != null)
                {
                    int index = indexAttr.Index;
                    if (columns[index] != null || fields[index] != null)
                    {
                        throw new InvalidOperationException($"Duplicate field index {index} in record type {typeof(TRecord).FullName}");
                    }

                    columns[index] = indexAttr;
                    fields[index]  = fld;
                }
            }

            if (columns.Any(c => c == null) ||
                fields.Any(f => f == null))
            {
                throw new InvalidOperationException($"Could not map all columns of record type {typeof(TRecord).FullName}.");
            }


            // map the stream data to fields.
            var records = new TRecord[RowCount];

            const int MaxFieldSize = 4;
            var       fieldBytes   = new byte[MaxFieldSize];

            for (int row = 0; row < RowCount; row++)
            {
                // note: in the case that TRecord is a struct, we box + unbox it so we can populate via reflection.
                object rec = new TRecord();

                int recBytes = 0;

                for (int col = 0; col < ColumnCount; col++)
                {
                    CMiniColDef colDef = _tableDef.m_Def.m_pColDefs[col];

                    if (recBytes != colDef.m_oColumn)
                    {
                        // skip past any padding bytes.
                        peStream.Seek(colDef.m_oColumn - recBytes, SeekOrigin.Current);

                        recBytes = colDef.m_oColumn;
                    }

                    peStream.Read(fieldBytes, 0, colDef.m_cbColumn);

                    fields[col].SetValue(rec, ConvertBytes(fieldBytes, colDef));

                    recBytes += colDef.m_cbColumn;
                }

                records[row] = (TRecord)rec;
            }

            return(records);
        }
Exemple #2
0
        private object ConvertBytes(byte[] bytes, CMiniColDef column)
        {
            // read RIDs, CodedTokens
            if (column.m_Type < MetaModel.iCodedTokenMax)
            {
                if (column.m_cbColumn == 2)
                {
                    return(BitConverter.ToUInt16(bytes, 0));
                }
                else if (column.m_cbColumn == 4)
                {
                    return(BitConverter.ToUInt32(bytes, 0));
                }

                throw new ArgumentException($"Unexpected data size for RID or Coded Token: {column.m_cbColumn} bytes");
            }
            else
            {
                // read types with specific values.
                ColumnType type = (ColumnType)column.m_Type;

                switch (type)
                {
                case ColumnType.String:
                case ColumnType.Guid:
                case ColumnType.Blob:
                    if (column.m_cbColumn == 2)
                    {
                        return(BitConverter.ToUInt16(bytes, 0));
                    }
                    else if (column.m_cbColumn == 4)
                    {
                        return(BitConverter.ToUInt32(bytes, 0));
                    }
                    break;

                case ColumnType.SHORT:
                    if (column.m_cbColumn == 2)
                    {
                        return(BitConverter.ToInt16(bytes, 0));
                    }
                    break;

                case ColumnType.USHORT:
                    if (column.m_cbColumn == 2)
                    {
                        return(BitConverter.ToUInt16(bytes, 0));
                    }
                    break;

                case ColumnType.LONG:
                    if (column.m_cbColumn == 4)
                    {
                        return(BitConverter.ToInt32(bytes, 0));
                    }
                    break;

                case ColumnType.ULONG:
                    if (column.m_cbColumn == 4)
                    {
                        return(BitConverter.ToUInt32(bytes, 0));
                    }
                    break;

                case ColumnType.BYTE:
                    if (column.m_cbColumn == 1)
                    {
                        return(bytes[0]);
                    }
                    break;

                default:
                    throw new ArgumentException($"Unrecognized column type '{type}'.");
                }

                throw new ArgumentException($"Unexpected data size for type {type}: {column.m_cbColumn} bytes");
            }
        }