コード例 #1
0
        /// <summary>
        /// Parses a database row.
        /// </summary>
        /// <returns></returns>
        SType ParseDBRow()
        {
            var header = GetObject() as SObjectType;

            if (header == null)
            {
                throw new ParserException("DBRow header not found");
            }

            if (!header.IsDBRowDescriptor)
            {
                throw new ParserException("Bad DBRow descriptor name");
            }

            var fields = header.Members.First().Members.First(
                member => member is STupleType).Members.First().Members.Cast <STupleType>().ToList();

            if (!fields.Any())
            {
                return(new SNoneType());
            }

            // Check for double marker in stream (usually found in a file with one DBRow)
            var length = m_reader.ReadLength();

            if (m_reader.IsDoubleMarker(length))
            {
                length = m_reader.ReadLength();
            }

            var unpackedDataSize = GetUnpackedDataSize(fields);
            var compressedData   = m_reader.ReadBytes(length);
            var uncompressedData = Rle_Unpack(compressedData, unpackedDataSize);

            var reader = new CachedFileReader(uncompressedData, false);

            // Find the maximum number of elements for each field member
            var maxElements = fields.Select(field => field.Members.Count).Concat(new[] { 0 }).Max();

            // The size of SDict must be the ammount of entries stored,
            // multiplied by the max elements of each field member
            var dict = new SDictType((uint)(fields.Count() * maxElements));
            var pass = 1;

            while (pass < 7)
            {
                // The pattern for what data to read on each pass is:
                // 1: 64 bit (Int64, Double)
                // 2: 32 bit (Int32, Single)
                // 3: 16 bit (Int16)
                // 4: 8 bit (Byte)
                // 5: 1 bit (Boolean)
                // 6: strings

                foreach (var field in fields)
                {
                    var fieldName = field.Members.First();
                    var fieldType = (SLongType)field.Members.Last();
                    var dbType    = (DbTypes)fieldType.Value;

                    byte  boolCount  = 0;
                    var   boolBuffer = false;
                    SType obj        = null;

                    switch (dbType)
                    {
                    case DbTypes.Short:
                    case DbTypes.UShort:
                        if (pass == 3)
                        {
                            obj = new SShortType(reader.ReadShort());
                        }
                        break;

                    case DbTypes.Int:
                    case DbTypes.UInt:
                        if (pass == 2)
                        {
                            obj = new SIntType(reader.ReadInt());
                        }
                        break;

                    case DbTypes.Float:
                        if (pass == 2)
                        {
                            obj = new SDoubleType(reader.ReadFloat());
                        }
                        break;

                    case DbTypes.Double:
                        if (pass == 1)
                        {
                            obj = new SDoubleType(reader.ReadDouble());
                        }
                        break;

                    case DbTypes.Currency:
                        if (pass == 1)
                        {
                            obj = new SDoubleType(reader.ReadLong() / 10000.0);
                        }
                        break;

                    case DbTypes.Long:
                    case DbTypes.ULong:
                    case DbTypes.Filetime:     // Timestamp
                    case DbTypes.DBTimestamp:
                        if (pass == 1)
                        {
                            obj = new SLongType(reader.ReadLong());
                        }
                        break;

                    case DbTypes.Bool:
                        if (pass == 5)
                        {
                            if (boolCount == 0)
                            {
                                boolBuffer = Convert.ToBoolean(reader.ReadByte());
                                boolCount++;
                            }

                            obj = boolBuffer && boolCount != 0
                                          ? new SBooleanType(1)
                                          : new SBooleanType(0);
                        }
                        break;

                    case DbTypes.Byte:
                    case DbTypes.UByte:
                        if (pass == 4)
                        {
                            obj = new SByteType(reader.ReadByte());
                        }
                        break;

                    case DbTypes.Bytes:     // String types
                    case DbTypes.String:
                    case DbTypes.WideString:
                        if (pass == 6)
                        {
                            obj = GetObject();
                        }
                        break;

                    default:
                        throw new ParserException("Unhandled db column type: " + dbType);
                    }

                    if (obj == null)
                    {
                        continue;
                    }

                    dict.AddMember(obj);
                    dict.AddMember(fieldName.Clone());
                }

                pass++;
            }

            var parsedDBRow = new STupleType(2);

            parsedDBRow.AddMember(header);
            parsedDBRow.AddMember(dict);
            return(parsedDBRow);
        }