Ejemplo n.º 1
0
        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();
            }
        }
Ejemplo n.º 2
0
        public static UInt32 WriteEntry(Stream dataStream, Stream tableStream, RpDbTableEntry entry, List <PropIdPair> order)
        {
            //Add the data and return the offset.
            UInt32 offset = (UInt32)dataStream.Position;

            //Write the offset and uuid to the table.
            WriterTools.WriteUInt32(tableStream, offset);
            WriterTools.WriteUInt32(tableStream, entry.uuid);
            //Now, we'll write the data.
            //Get the serialized data for this class, following the order offered.
            byte[][] serData = new byte[order.Count][]; //Data to be serialized.
            for (int i = 0; i < order.Count; i++)
            {
                //This is run for each property in this. Serialize it.
                var pair = order[i];
                var prop = pair.prop;
                //Get the value from this using the property found earlier.
                object value = prop.GetValue(entry.data, null);
                Type   type  = value.GetType();
                //Convert this to bytes.
                byte[] data = GetSerializedData(value, type);
                //Add it.
                serData[i] = data;
            }
            //Write UUID
            WriterTools.WriteUInt32(dataStream, entry.uuid);
            //Write the lengths
            foreach (byte[] d in serData)
            {
                WriterTools.WriteUInt16(dataStream, (ushort)d.Length);
            }
            //Now, write all the data.
            foreach (byte[] d in serData)
            {
                dataStream.Write(d, 0, d.Length);
            }

            //Return offset.
            return(offset);
        }
Ejemplo n.º 3
0
        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);
        }