예제 #1
0
        public DBFile ReadFile(BinaryReader reader, DBFileHeader header, TypeInfo info)
        {
            reader.BaseStream.Position = header.Length;
            DBFile file = new DBFile(header, info);
            int    i    = 0;

            while (reader.BaseStream.Position < reader.BaseStream.Length)
            {
                try
                {
                    file.Entries.Add(ReadFields(reader, info));
                    i++;
                }
                catch (Exception x)
                {
                    string message = string.Format("{2} at entry {0}, db version {1}", i, file.Header.Version, x.Message);
                    throw new DBFileNotSupportedException(message, x);
                }
            }
            if (file.Entries.Count != header.EntryCount)
            {
                throw new DBFileNotSupportedException(string.Format("Expected {0} entries, got {1}", header.EntryCount, file.Entries.Count));
            }
            else if (reader.BaseStream.Position != reader.BaseStream.Length)
            {
                throw new DBFileNotSupportedException(string.Format("Expected {0} bytes, read {1}", header.Length, reader.BaseStream.Position));
            }
            return(file);
        }
예제 #2
0
        /*
         * Reads a db file from stream, using the version information
         * contained in the header read from it.
         */
        public DBFile Decode(Stream stream)
        {
            BinaryReader reader = new BinaryReader(stream);

            reader.BaseStream.Position = 0;
            DBFileHeader    header = readHeader(reader);
            List <TypeInfo> infos  = DBTypeMap.GetVersionedInfos(typeName, header.Version);

            if (infos.Count == 0)
            {
                infos.AddRange(DBTypeMap.GetAllInfos(typeName));
            }
            foreach (TypeInfo realInfo in infos)
            {
                try
                {
#if DEBUG
                    Console.WriteLine("Parsing version {1} with info {0}", string.Join(",", realInfo.Fields), header.Version);
#endif
                    DBFile result = ReadFile(reader, header, realInfo);
                    return(result);
                }
                catch (Exception) { }
            }
            return(null);
            // throw new DBFileNotSupportedException(string.Format("No applicable type definition found"));
        }
예제 #3
0
        /*
         * Query if given packed file can be decoded.
         * Is not entirely reliable because it only reads the header and checks if a
         * type definition is available for the given GUID and/or type name and version.
         * The actual decode tries out all available type infos for that type name
         * but that is less efficient because it has to read the whole file at least once
         * if successful.
         */
        public static bool CanDecode(PackedFile packedFile, out string display)
        {
            bool   result = true;
            string key    = DBFile.Typename(packedFile.FullPath);

            if (DBTypeMap.IsSupported(key))
            {
                try
                {
                    DBFileHeader header     = PackedFileDbCodec.readHeader(packedFile);
                    int          maxVersion = DBTypeMap.MaxVersion(key);
                    if (maxVersion != 0 && header.Version > maxVersion)
                    {
                        display = string.Format("{0}: needs {1}, has {2}", key, header.Version, DBTypeMap.MaxVersion(key));
                        result  = false;
                    }
                    else
                    {
                        display = string.Format("Version: {0}", header.Version);
                    }
                }
                catch (Exception x)
                {
                    display = string.Format("{0}: {1}", key, x.Message);
                }
            }
            else
            {
                display = string.Format("{0}: no definition available", key);
                result  = false;
            }
            return(result);
        }
예제 #4
0
        public override bool Equals(object other)
        {
            bool result = false;

            if (other is DBFileHeader)
            {
                DBFileHeader header2 = (DBFileHeader)other;
                result  = GUID.Equals(header2.GUID);
                result &= Version.Equals(header2.Version);
                result &= EntryCount.Equals(header2.EntryCount);
            }
            return(result);
        }
예제 #5
0
 public static void WriteHeader(BinaryWriter writer, DBFileHeader header)
 {
     if (header.GUID != "")
     {
         writer.Write(GUID_MARKER);
         IOFunctions.WriteCAString(writer, header.GUID, Encoding.Unicode);
     }
     if (header.Version != 0)
     {
         writer.Write(VERSION_MARKER);
         writer.Write(header.Version);
     }
     writer.Write((byte)1);
     writer.Write(header.EntryCount);
 }
예제 #6
0
        public static DBFileHeader readHeader(BinaryReader reader)
        {
            byte   index      = reader.ReadByte();
            int    version    = 0;
            string guid       = "";
            bool   hasMarker  = false;
            uint   entryCount = 0;

            try
            {
                if (index != 1)
                {
                    // I don't think those can actually occur more than once per file
                    while (index == 0xFC || index == 0xFD)
                    {
                        var bytes = new List <byte>(4);
                        bytes.Add(index);
                        bytes.AddRange(reader.ReadBytes(3));
                        UInt32 marker = BitConverter.ToUInt32(bytes.ToArray(), 0);
                        if (marker == GUID_MARKER)
                        {
                            guid  = IOFunctions.ReadCAString(reader, Encoding.Unicode);
                            index = reader.ReadByte();
                        }
                        else if (marker == VERSION_MARKER)
                        {
                            hasMarker = true;
                            version   = reader.ReadInt32();
                            index     = reader.ReadByte();
                            // break;
                        }
                        else
                        {
                            throw new DBFileNotSupportedException(string.Format("could not interpret {0}", marker));
                        }
                    }
                }
                entryCount = reader.ReadUInt32();
            }
            catch
            {
            }
            DBFileHeader header = new DBFileHeader(guid, version, entryCount, hasMarker);

            return(header);
        }
예제 #7
0
        /*
         * Add data contained in the given db file to this one.
         */
        public void Import(DBFile file)
        {
            if (CurrentType.Name != file.CurrentType.Name)
            {
                throw new DBFileNotSupportedException
                          ("File type of imported DB doesn't match that of the currently opened one", this);
            }
            // check field type compatibility
            for (int i = 0; i < file.CurrentType.Fields.Count; i++)
            {
                if (file.CurrentType.Fields [i].TypeCode != CurrentType.Fields [i].TypeCode)
                {
                    throw new DBFileNotSupportedException
                              ("Data structure of imported DB doesn't match that of currently opened one at field " + i, this);
                }
            }
            DBFileHeader h = file.Header;

            Header      = new DBFileHeader(h.GUID, h.Version, h.EntryCount, h.HasVersionMarker);
            CurrentType = file.CurrentType;
            // this.entries = new List<List<FieldInstance>> ();
            entries.AddRange(file.entries);
            Header.EntryCount = (uint)entries.Count;
        }
예제 #8
0
 /*
  * Create copy of given header.
  */
 public DBFileHeader(DBFileHeader toCopy) : this(toCopy.GUID, toCopy.Version, 0, toCopy.HasVersionMarker)
 {
 }
예제 #9
0
 /*
  * Create copy of the given db file.
  */
 public DBFile(DBFile toCopy) : this(toCopy.Header, toCopy.CurrentType)
 {
     Header = new DBFileHeader(toCopy.Header.GUID, toCopy.Header.Version, toCopy.Header.EntryCount, toCopy.Header.HasVersionMarker);
     // we need to create a new instance for every field so we don't write through to the old data
     toCopy.entries.ForEach(entry => entries.Add(new DBRow(toCopy.CurrentType, entry)));
 }
예제 #10
0
 /*
  * Create db file with the given header and the given type.
  */
 public DBFile(DBFileHeader h, TypeInfo info)
 {
     Header      = h;
     CurrentType = info;
 }