private static void writeMetadataTableInfo(FileStream metadataStream, MetadataTableInfo info, int offset)
 {
     metadataStream.WriteASCII(info.identifier, offset);
     metadataStream.WriteInt(info.tableOffset.value, offset + IDENTIFIER_LENGTH);
     metadataStream.WriteInt(info.numEntries, offset + 4 + IDENTIFIER_LENGTH);
     metadataStream.WriteInt(info.totalLength, offset + 8 + IDENTIFIER_LENGTH);
 }
        private static MetadataTableInfo readMetadataTableInfo(FileStream metadataStream, int offset)
        {
            MetadataTableInfo info = new MetadataTableInfo();

            info.identifier  = metadataStream.ReadASCII(offset, IDENTIFIER_LENGTH);
            info.tableOffset = new Pointer(metadataStream.ReadData(offset + IDENTIFIER_LENGTH, 4));
            info.numEntries  = metadataStream.ReadInt(offset + 4 + IDENTIFIER_LENGTH);
            info.totalLength = metadataStream.ReadInt(offset + 8 + IDENTIFIER_LENGTH);

            return(info);
        }
        private static void initializeMetadata(FileStream metadataStream)
        {
            MetadataTableInfo mainTable = new MetadataTableInfo();

            mainTable.identifier  = "MAIN";
            mainTable.totalLength = 0x0;
            mainTable.numEntries  = 0x0;
            mainTable.tableOffset = new Pointer(0x10);

            writeMetadataTableInfo(metadataStream, mainTable, 0);
            metadataStream.Flush();
        }
        private static Metadata readMetadataTable(FileStream metadataStream, int offset)
        {
            MetadataTableInfo           info  = readMetadataTableInfo(metadataStream, offset);
            List <Tuple <int, byte[]> > table = new List <Tuple <int, byte[]> >();
            int offs_acc = info.tableOffset.value;

            for (int i = 0; i < info.numEntries; i++)
            {
                table.Add(readMetadataEntry(metadataStream, offs_acc));
                offs_acc += metadataStream.ReadInt(offs_acc) + 4;
                offs_acc  = HexTools.align(offs_acc); //word align
            }
            Metadata ret = new Metadata();

            ret.data = table;
            ret.info = info;
            return(ret);
        }
        /*private void rewriteMain()
         * {
         *  //Note!! The new main must take the same or less space than the previous.
         *  //Rewrites from tables;
         *  for(var table in tables)
         *  {
         *
         *
         *  }
         *
         * }*/

        private void quickWrite(string iden)
        {
            //precondition that iden is in tables
            metadataStream = File.Open(metadataPath, FileMode.Open);
            Metadata updated = tables[iden];
            List <Tuple <int, byte[]> > tables_raw = mainTable.data;
            //string current;
            Pointer?ret = getTableOffset(iden);

            if (!ret.HasValue)
            {
                metadataStream.Close();
                writeMetadata();
                return;
            }
            Pointer           tableOffset = ret.Value;
            MetadataTableInfo cur_info    = readMetadataTableInfo(metadataStream, tableOffset.value);

            if (updated.info.totalLength <= cur_info.totalLength)
            {
                //free to write over
                writeMetadataTableInfo(metadataStream, updated.info, tableOffset.value);
                metadataStream.Seek(updated.info.tableOffset.value, SeekOrigin.Begin);
            }
            else
            {
                //write at the end
                updated.info.tableOffset = new Pointer((int)metadataStream.Length);
                writeMetadataTableInfo(metadataStream, updated.info, tableOffset.value);
                metadataStream.Seek(0, SeekOrigin.End);
            }
            foreach (var entry in updated.data)
            {
                var len = BitConverter.GetBytes((int)entry.Item1);
                metadataStream.Write(len, 0, 4);
                metadataStream.Write(entry.Item2, 0, entry.Item2.Length);
            }
            metadataStream.Close();
        }
        public void writeMetadata()
        {
            //metadataStream.Seek(0, SeekOrigin.Begin);

            //TODO
            //Load all tables into RAM, erase the file, rewrite all the tables.
            mainTable.info.numEntries = tables.Count;

            metadataStream = File.Open(metadataPath, FileMode.Open);

            MetadataTableInfo[] tableInfo = new MetadataTableInfo[tables.Count];
            var myData = new List <Metadata>();

            foreach (var table in tables)
            {
                myData.Add(table.Value);
            }

            for (int i = 0; i < tables.Count; i++)
            {
                tableInfo[i] = myData[i].info;
            }
            int [] tableInfoOffsets = new int[myData.Count];

            int offs_acc = TABLE_INFO_SIZE;

            for (int i = 0; i < myData.Count; i++)
            {
                tableInfoOffsets[i] = offs_acc;
                MetadataTableInfo curTable;
                curTable  = myData[i].info;
                offs_acc += TABLE_INFO_SIZE;
            }

            mainTable.info.tableOffset = new Pointer(offs_acc); //start of main data
            //mainTable.data = new List<Tuple<int, byte[]>>();

            //now write the main table
            for (int i = 0; i < myData.Count; i++)
            {
                metadataStream.WriteInt(4, offs_acc);
                offs_acc += 4;
                metadataStream.WriteInt(tableInfoOffsets[i], offs_acc);
                offs_acc += 4;
                //mainTable.data.Add(Tuple.Create(4, BitConverter.GetBytes(tableInfoOffsets[i])));
            }

            //now write all the other tables' data
            for (int i = 0; i < myData.Count; i++)
            {
                tableInfo[i].tableOffset = new Pointer(offs_acc);
                for (int j = 0; j < myData[i].data.Count; j++)
                {
                    int len = myData[i].data[j].Item1;
                    metadataStream.WriteInt(len, offs_acc); //length
                    offs_acc += 4;
                    metadataStream.Seek(offs_acc, SeekOrigin.Begin);
                    metadataStream.Write(myData[i].data[j].Item2, 0, len);
                    offs_acc += len;
                    int align_diff = HexTools.align(offs_acc) - offs_acc;
                    if (align_diff != 0)
                    {
                        byte[] alignment = new byte[align_diff];
                        Array.Clear(alignment, 0, align_diff);
                        metadataStream.Write(alignment, 0, align_diff);
                    }
                    offs_acc += align_diff;
                }
            }
            metadataStream.SetLength(offs_acc);

            //now go back to the top and write all the table data
            writeMetadataTableInfo(metadataStream, mainTable.info, 0);
            offs_acc = TABLE_INFO_SIZE;

            for (int i = 0; i < myData.Count; i++)
            {
                writeMetadataTableInfo(metadataStream, tableInfo[i], offs_acc);
                offs_acc += TABLE_INFO_SIZE;
            }

            mainTable = readMetadataTable(metadataStream, 0);

            metadataStream.Flush();
            metadataStream.Close();

            //And we're done.


            //All headers, then all data
            //TableData1, TableData2, TableData3, . . .
            //length, dataaaaaaaaaaaa; length, dataaaaaaaaaaaaa, . . .
        }
 private static void writeMetadataTableInfo(FileStream metadataStream, MetadataTableInfo info, int offset)
 {
     metadataStream.WriteASCII(info.identifier, offset);
     metadataStream.WriteInt(info.tableOffset.value, offset + IDENTIFIER_LENGTH);
     metadataStream.WriteInt(info.numEntries, offset + 4 + IDENTIFIER_LENGTH);
     metadataStream.WriteInt(info.totalLength, offset + 8 + IDENTIFIER_LENGTH);
 }
        private static MetadataTableInfo readMetadataTableInfo(FileStream metadataStream, int offset)
        {
            MetadataTableInfo info = new MetadataTableInfo();

            info.identifier = metadataStream.ReadASCII(offset, IDENTIFIER_LENGTH);
            info.tableOffset = new Pointer(metadataStream.ReadData(offset + IDENTIFIER_LENGTH, 4));
            info.numEntries = metadataStream.ReadInt(offset + 4 + IDENTIFIER_LENGTH);
            info.totalLength = metadataStream.ReadInt(offset + 8 + IDENTIFIER_LENGTH);

            return info;
        }
        private static void initializeMetadata(FileStream metadataStream)
        {
            MetadataTableInfo mainTable = new MetadataTableInfo();
            mainTable.identifier = "MAIN";
            mainTable.totalLength = 0x0;
            mainTable.numEntries = 0x0;
            mainTable.tableOffset = new Pointer(0x10);

            writeMetadataTableInfo(metadataStream, mainTable, 0);
            metadataStream.Flush();
        }
        public void writeMetadata()
        {
            //metadataStream.Seek(0, SeekOrigin.Begin);

            //TODO
            //Load all tables into RAM, erase the file, rewrite all the tables.
            mainTable.info.numEntries = tables.Count;

            metadataStream = File.Open(metadataPath, FileMode.Open);

            MetadataTableInfo[] tableInfo = new MetadataTableInfo[tables.Count];
            var myData = new List<Metadata>();
            foreach(var table in tables)
            {
                myData.Add(table.Value);
            }

            for(int i=0; i<tables.Count; i++)
            {
                tableInfo[i] = myData[i].info;
            }
            int [] tableInfoOffsets = new int[myData.Count];

            int offs_acc = TABLE_INFO_SIZE;

            for(int i=0; i<myData.Count; i++)
            {
                tableInfoOffsets[i] = offs_acc;
                MetadataTableInfo curTable;
                curTable = myData[i].info;
                offs_acc += TABLE_INFO_SIZE;
            }

            mainTable.info.tableOffset = new Pointer(offs_acc); //start of main data
            //mainTable.data = new List<Tuple<int, byte[]>>();

            //now write the main table
            for (int i = 0; i < myData.Count; i++)
            {
                metadataStream.WriteInt(4, offs_acc);
                offs_acc += 4;
                metadataStream.WriteInt(tableInfoOffsets[i], offs_acc);
                offs_acc += 4;
                //mainTable.data.Add(Tuple.Create(4, BitConverter.GetBytes(tableInfoOffsets[i])));
            }

            //now write all the other tables' data
            for (int i=0; i<myData.Count; i++)
            {
                tableInfo[i].tableOffset = new Pointer(offs_acc);
                for(int j=0; j<myData[i].data.Count; j++)
                {
                    int len = myData[i].data[j].Item1;
                    metadataStream.WriteInt(len, offs_acc); //length
                    offs_acc += 4;
                    metadataStream.Seek(offs_acc, SeekOrigin.Begin);
                    metadataStream.Write(myData[i].data[j].Item2, 0, len);
                    offs_acc += len;
                    int align_diff = HexTools.align(offs_acc) - offs_acc;
                    if(align_diff!=0)
                    {
                        byte[] alignment = new byte[align_diff];
                        Array.Clear(alignment, 0, align_diff);
                        metadataStream.Write(alignment, 0, align_diff);
                    }
                    offs_acc += align_diff;
                }
            }
            metadataStream.SetLength(offs_acc);

            //now go back to the top and write all the table data
            writeMetadataTableInfo(metadataStream, mainTable.info, 0);
            offs_acc = TABLE_INFO_SIZE;

            for (int i = 0; i < myData.Count; i++)
            {
                writeMetadataTableInfo(metadataStream, tableInfo[i], offs_acc);
                offs_acc += TABLE_INFO_SIZE;
            }

            mainTable = readMetadataTable(metadataStream, 0);

            metadataStream.Flush();
            metadataStream.Close();

            //And we're done.

            //All headers, then all data
            //TableData1, TableData2, TableData3, . . .
            //length, dataaaaaaaaaaaa; length, dataaaaaaaaaaaaa, . . .
        }