Exemple #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);
        }
Exemple #2
0
        /// <summary>
        /// Gets an object from the data.
        /// </summary>
        /// <returns></returns>
        SType GetObject()
        {
            SType sObject   = null;
            var   type      = m_reader.ReadByte();
            var   checkType = (StreamType)(type & ~(byte)StreamType.SharedFlag);
            var   shared    = Convert.ToBoolean(type & (byte)StreamType.SharedFlag);

            switch (checkType)
            {
            case 0:
            case StreamType.StreamStart:
                break;

            case StreamType.Marker:
                break;

            case StreamType.None:
                sObject = new SNoneType();
                break;

            case StreamType.Utf8:
                sObject = new SStringType(m_reader.ReadUtf8String(m_reader.ReadLength()));
                break;

            case StreamType.String:
            case StreamType.StringLong:
                sObject = new SStringType(m_reader.ReadString(m_reader.ReadLength()));
                break;

            case StreamType.StringGlobal:
                sObject = new SStringType(m_reader.ReadString(m_reader.ReadLength()));
                CheckShared(shared, sObject);
                break;

            case StreamType.StringUnicode:
                sObject = new SStringType(m_reader.ReadUnicodeString(m_reader.ReadLength() * 2));
                break;

            case StreamType.Long:
                sObject = new SLongType(m_reader.ReadLong());
                break;

            case StreamType.Int:
                sObject = new SIntType(m_reader.ReadInt());
                break;

            case StreamType.Short:
                sObject = new SShortType(m_reader.ReadShort());
                break;

            case StreamType.Byte:
                sObject = new SByteType(m_reader.ReadByte());
                break;

            case StreamType.IntNegOne:
                sObject = new SIntType(-1);
                break;

            case StreamType.IntZero:
                sObject = new SIntType(0);
                break;

            case StreamType.IntOne:
                sObject = new SIntType(1);
                break;

            case StreamType.Double:
                sObject = new SDoubleType(m_reader.ReadDouble());
                break;

            case StreamType.DoubleZero:
                sObject = new SDoubleType(0);
                break;

            case StreamType.StringEmpty:
                sObject = new SStringType(null);
                break;

            case StreamType.StringOne:
                sObject = new SStringType(m_reader.ReadString(1));
                break;

            case StreamType.StringRef:
                var id = m_reader.ReadByte();
                sObject = new SReferenceType(id, StringsTable.GetStringByID(id));
                break;

            case StreamType.StringIdent:
                sObject = new SIdentType(m_reader.ReadString(m_reader.ReadLength()));
                CheckShared(shared, sObject);
                break;

            case StreamType.Tuple:
            {
                var length = m_reader.ReadLength();
                sObject = new STupleType((uint)length);
                CheckShared(shared, sObject);
                Parse(sObject, length);
                break;
            }

            case StreamType.List:
            {
                var length = m_reader.ReadLength();
                sObject = new SListType((uint)length);
                CheckShared(shared, sObject);
                Parse(sObject, length);
                break;
            }

            case StreamType.Dict:
            {
                var length = (m_reader.ReadLength() * 2);
                sObject = new SDictType((uint)length);
                CheckShared(shared, sObject);
                Parse(sObject, length);
                break;
            }

            case StreamType.SharedObj:
                sObject = m_reader.GetSharedObj(m_reader.ReadLength() - 1);
                break;

            case StreamType.Checksum:
                sObject = new SStringType("checksum");
                m_reader.ReadInt();
                break;

            case StreamType.BoolTrue:
                sObject = new SBooleanType(1);
                break;

            case StreamType.BoolFalse:
                sObject = new SBooleanType(0);
                break;

            case StreamType.ClassObject:
            case StreamType.NewObj:
            case StreamType.Object:
            {
                var storedId = m_reader.ReserveSlot(shared);
                sObject = ParseObject();
                m_reader.UpdateSlot(storedId, sObject);
            }
            break;

            case StreamType.TupleEmpty:
                sObject = new STupleType(0);
                break;

            case StreamType.TupleOne:
                sObject = new STupleType(1);
                CheckShared(shared, sObject);
                Parse(sObject);
                break;

            case StreamType.ListEmpty:
                sObject = new SListType(0);
                CheckShared(shared, sObject);
                break;

            case StreamType.ListOne:
                sObject = new SListType(1);
                CheckShared(shared, sObject);
                Parse(sObject);
                break;

            case StreamType.StringUnicodeEmpty:
                sObject = new SStringType(String.Empty);
                break;

            case StreamType.StringUnicodeOne:
                sObject = new SStringType(m_reader.ReadString(2));
                break;

            case StreamType.CompressedDBRow:
                sObject = ParseDBRow();
                break;

            case StreamType.SubStream:
                sObject = ParseSubStream();
                CheckShared(shared, sObject);
                break;

            case StreamType.TupleTwo:
                sObject = new STupleType(2);
                CheckShared(shared, sObject);
                Parse(sObject, 2);
                break;

            case StreamType.BigInt:
                sObject = new SLongType(m_reader.ReadBigInt());
                CheckShared(shared, sObject);
                break;

            default:
                throw new ParserException(
                          String.Format(CultureInfo.InvariantCulture,
                                        "Can't identify type {0:x2} at position {1:x2} [{1}] and length {2}",
                                        type, m_reader.Position, m_reader.Length));
            }

            if (sObject == null && type != (byte)StreamType.Marker)
            {
                throw new ParserException("An object could not be created");
            }

            return(sObject);
        }