コード例 #1
0
ファイル: DatabaseWriter.cs プロジェクト: Roman-Port/RpDb
        public static void WriteDatabase(Stream s, RpDbTable[] tables)
        {
            //We'll rewind to the beginning of the stream and begin writing.  https://docs.google.com/document/d/1PVuW3CshGg0BvQHSyrGBQhFceaTk92H3Fv8uKOkhpX8/edit
            //Write the name of this.
            WriterTools.WriteChars(s, new char[] { 'R', 'p', 'D', 'b' });
            //Write the version.
            WriterTools.WriteUInt16(s, RpDbDatabase.RPDB_VERSION);
            //Skip 32 bytes. These'll be used later.
            s.Position += 32;

            //We're going to write each table's data now.
            MemoryStream[] streams = new MemoryStream[tables.Length];
            Parallel.For(0, tables.Length, delegate(int i)
            {
                //Open MemoryStream for this table.
                MemoryStream stream = new MemoryStream();
                RpDbTable table     = tables[i];
                //Write table.
                TableWriter.WriteTable(stream, table);
                //Save this stream.
                streams[i] = stream;
            });

            //Now, we'll write the table TOC.
            //Write the number of entries.
            WriterTools.WriteUInt16(s, (UInt16)tables.Length);
            //Now, write all of the entries.
            UInt32 offset = 0;

            for (int i = 0; i < tables.Length; i++)
            {
                RpDbTable    table  = tables[i];
                MemoryStream stream = streams[i];
                //Write the offset and the name.
                WriterTools.WriteUInt32(s, offset);
                //Now, the name.
                WriterTools.WriteString(s, table.name);
                //Add the offset.
                offset += (UInt32)stream.Length;
            }
            //Now, write all of the streams in order.
            for (int i = 0; i < streams.Length; i++)
            {
                MemoryStream stream = streams[i];
                stream.Position = 0;
                stream.CopyTo(s);
                //Clear
                stream.Close();
                stream.Dispose();
            }
        }
コード例 #2
0
        public static RpDbTableEntry ReadEntry(Stream s, RpDbTable table)
        {
            //Create object.
            RpDbTableEntry entry = new RpDbTableEntry(table, null);

            entry.offset = (UInt32)s.Position;
            //First, read in the UUID.
            UInt32 uuid = ReaderTools.ReadUInt32(s);

            entry.uuid = uuid;
            //Read in the lengths.
            UInt16[] lengths = new UInt16[table.typeOrder.Length];
            for (int i = 0; i < table.typeOrder.Length; i++)
            {
                lengths[i] = ReaderTools.ReadUInt16(s);
            }
            //Now, read in the data
            object obj = Activator.CreateInstance(table.type);

            for (int i = 0; i < table.typeOrder.Length; i++)
            {
                Writer.PropIdPair pair = table.typeOrder[i];
                //Skip this if the length is zero. (it's null)
                UInt16 length = lengths[i];
                if (length != 0)
                {
                    //Read in the data.
                    byte[] buf = new byte[length];
                    s.Read(buf, 0, length);
                    //Todo: Actually get the data from it.
                    //For now, just read it in as a string
                    object d = Encoding.UTF8.GetString(buf);
                    //Now, set it inside the object.
                    pair.prop.SetValue(obj, d, null);
                }
            }
            //Set the entry's object to this.
            entry.data = obj;
            //Return the entry.
            return(entry);
        }
コード例 #3
0
        public static RpDbTable ReadTable(Stream s, Type[] types, RpDbDatabase database)
        {
            //Read the table name.
            string name = ReaderTools.ReadString(s);
            //Read the type
            string typeName = ReaderTools.ReadString(s);
            //Determine the type.
            Type t = null;

            //Loop through types and find match.
            foreach (Type tt in types)
            {
                if (tt.ToString() == typeName)
                {
                    t = tt;
                }
            }
            //Check if it was found.
            if (t == null)
            {
                throw new Exception("Failed to find type '" + typeName + "'.");
            }
            //Create the object.
            RpDbTable table = new RpDbTable(name, t, database);
            //Read the number of entries.
            UInt32 entryCount = ReaderTools.ReadUInt32(s);
            //Read number of types.
            UInt16 typeCount = ReaderTools.ReadUInt16(s);

            //Read the type table in. This'll give us the order.
            Writer.PropIdPair[] order = new Writer.PropIdPair[typeCount];
            for (int i = 0; i < typeCount; i++)
            {
                //Read in.
                UInt16      typeId = ReaderTools.ReadUInt16(s);
                ClassAttrib attr   = null;
                System.Reflection.PropertyInfo chosenProp = null;
                //Find this in the object.
                foreach (var prop in table.type.GetProperties())
                {
                    //Check the UUID.
                    ClassAttrib propAttr = Writer.TableWriter.GetUuidFromProperty(prop);
                    //If there is no UUID, skip this.
                    if (propAttr == null)
                    {
                        continue;
                    }
                    //Add this to the order if it matches
                    if (propAttr.uuid == typeId)
                    {
                        attr       = propAttr;
                        chosenProp = prop;
                    }
                }
                if (attr != null && chosenProp != null)
                {
                    order[i] = new Writer.PropIdPair(chosenProp, typeId);
                }
                else
                {
                    Console.WriteLine("No attr found for ID " + typeId.ToString() + ".");
                }
            }
            table.typeOrder = order;
            //Now that we know the order of the types, we can read it in.
            //Skip 32 bytes of reserved data.
            s.Position += 32;
            //Read each of the offsets in. Add them to the dict as we go.
            for (int i = 0; i < entryCount; i++)
            {
                //Read offset
                UInt32 offset = ReaderTools.ReadUInt32(s);
                //Read UUID
                UInt32 uuid = ReaderTools.ReadUInt32(s);
                //Insert.
                table.uuidLookup.Add(uuid, offset);
            }
            //Now, the data begins. Add the flag.
            table.tableDataOffset = s.Position;
            //We can now continue to the next table.
            return(table);
        }
コード例 #4
0
ファイル: TableWriter.cs プロジェクト: Roman-Port/RpDb
        public static void WriteTable(Stream s, RpDbTable table)
        {
            //First, write the table name.
            WriterTools.WriteString(s, table.name);
            //Write the type name.
            WriterTools.WriteString(s, table.type.ToString());
            //Now, write the number of entries.
            WriterTools.WriteUInt32(s, (UInt32)table.GetNumberOfEntries());
            //Write the type table now. Go through each attribute in the type.
            //Determine the order.
            List <PropIdPair> order = new List <PropIdPair>();

            foreach (var prop in table.type.GetProperties())
            {
                //Check the UUID.
                ClassAttrib propAttr = GetUuidFromProperty(prop);
                //If there is no UUID, skip this.
                if (propAttr == null)
                {
                    Console.WriteLine("(debug) Skipping because no attr.");
                    continue;
                }
                //Add this to the order.
                order.Add(new PropIdPair(prop, propAttr.uuid));
            }
            //Now, write number of types.
            WriterTools.WriteUInt16(s, (UInt16)order.Count);
            //Write the type table itself.
            foreach (PropIdPair o in order)
            {
                WriterTools.WriteUInt16(s, o.typeid);
            }
            //Skip 32 bytes of reserved space.
            s.Position += 32;
            //Now, we'll find all the entries and put them in a stream.
            //We'll create a stream for the actual data and copy it here later.
            MemoryStream dataStream = new MemoryStream();
            //We'll now find and include data.

            //First, find new entries.

            List <UInt32> uuidsToSkip = new List <uint>(); //These are the UUIDs that we will skip when we copy directly from the unmodified enteries.

            foreach (RpDbTableEntry entry in table.modifyBuffer.Values)
            {
                //Check if this key exists in the uuid lookup. If it does, this is a UPDATED entry. If it doesn't, this is a NEW entry.
                bool existsBefore = table.uuidLookup.ContainsKey(entry.uuid);
                //Add this now.
                UInt32 offset = ValueWriter.WriteEntry(dataStream, s, entry, order);
                //Add this to the written dictonary, but also add it to the skipped list so we don't rewrite it.
                uuidsToSkip.Add(entry.uuid);
                entry.offset = offset;
                //Make sure we know the offset.
                if (!existsBefore)
                {
                    //If this wasn't already in the lookup table, add it.
                    table.uuidLookup.Add(entry.uuid, offset);
                }
                else
                {
                    //Update the offset now.
                    table.uuidLookup[entry.uuid] = offset;
                }
            }

            //Now, we'll add existing, untouched, files.
            foreach (var entry in table.uuidLookup)
            {
                //Check if this is in the "uuidstoskip" list.
                if (!uuidsToSkip.Contains(entry.Key))
                {
                    //We'll copy this to the new one.
                    //TODO: COPY!!!!!!!!!!!
                    throw new NotImplementedException();
                }
            }

            //Now that that is done, we can copy the data stream to the main stream.
            dataStream.Position = 0;
            dataStream.CopyTo(s);
        }