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;
 }
        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, . . .
        }
        public void setMetadataTable(string identifier, byte[][] table)
        {
            Metadata toAdd = new Metadata();
            toAdd.info = new MetadataTableInfo();
            toAdd.data = new List<Tuple<int, byte[]>>();

            toAdd.info.identifier = identifier;
            toAdd.info.numEntries = table.Length;
            toAdd.info.tableOffset = new Pointer(0); //Placeholder; determined upon write

            int len = 0;
            foreach(byte[] entry in table)
            {
                len += 4;
                int entry_len = entry.Length;
                len += entry_len;
                toAdd.data.Add(Tuple.Create(entry_len, entry));

            }

            toAdd.info.totalLength = len;

            if(tables.ContainsKey(identifier))
            {
                tables[identifier] = toAdd;
                quickWrite(identifier);
            }
            else
            {
                tables[identifier] = toAdd;
                writeMetadata();
            }
            //placeholder until metadata is written
            //myData.Add(toAdd);
        }
 public void setMetadataTable(string identifier, Metadata meta)
 {
     if (tables.ContainsKey(identifier))
     {
         tables[identifier] = meta;
         quickWrite(identifier);
     }
     else
     {
         tables[identifier] = meta;
         writeMetadata();
     }
 }
        //private List<Metadata> myData;
        //List<MetadataTable> tables; //maybe in the works for more efficient refactoring
        public MetadataManager(string filePath)
        {
            this.metadataPath = filePath;
            if (!File.Exists(filePath))
            {
                metadataStream = File.Open(filePath, FileMode.CreateNew);
                initializeMetadata(metadataStream);
            }
            else
            { metadataStream = File.Open(filePath, FileMode.Open); }

            tables = new Dictionary<string, Metadata>();
            //myData = new List<Metadata>();

            mainTable = readMetadataTable(metadataStream, 0);//new Metadata();
            //mainTable.info = readMetadataTableInfo(metadataStream, 0);

            int numTables = mainTable.info.numEntries;
            int offs = mainTable.info.tableOffset.value;

            //int offs = 4;
            for (int i = 0; i < numTables; i++)
            {
                offs += 4; //ignore length data; constant length
                Pointer tableOffs = new Pointer(metadataStream.ReadData(offs,4)); //Get the pointer to the data table
                Metadata temp = readMetadataTable(metadataStream, tableOffs.value);
                offs += 4;
                string identifier = metadataStream.ReadASCII(tableOffs.value, IDENTIFIER_LENGTH); //read the identifier of the data table
                tables.Add(identifier, temp);
                //myData.Add(temp);
            }
            metadataStream.Close();
        }