private unsafe void Write(uint id, byte[] rawdata) { if (!StreamMul.CanWrite || (StreamIdx != null && !StreamIdx.CanWrite)) { throw new AccessViolationException("Can't write data to mul file"); } if (id >= _EntryLength || (IdxTable == null && rawdata != null && rawdata.Length != EntrySize)) { throw new ArgumentOutOfRangeException(); } if (IdxTable == null) { StreamMul.Seek(_EntryOff + id * EntrySize, SeekOrigin.Begin); } else { if (rawdata != null) { var length = IdxTable[id].Length; IdxTable[id].Length = (uint)rawdata.Length; if (IdxTable[id].Offset != 0xFFFFFFFF && length != 0xFFFFFFFF && length >= IdxTable[id].Length) { StreamMul.Seek(IdxTable[id].Offset, SeekOrigin.Begin); } else { IdxTable[id].Offset = (uint)StreamMul.Seek(0, SeekOrigin.End); } } else { (this as IDataContainer).Delete(id); } StreamIdx.Seek((_EntryOff + id) * sizeof(IndexEntry), SeekOrigin.Begin); Utils.ArrayWrite <IndexEntry>(StreamIdx, IdxTable, (int)id, 1); StreamIdx.Flush(); } if (rawdata != null) { Utils.ArrayWrite <byte>(StreamMul, rawdata, 0, rawdata.Length); StreamMul.Flush(); } }
T[] IDataContainer.Read <T>(uint fromId, uint offset, uint count) { if (IdxTable != null) { if (IdxTable[fromId].Offset == 0xFFFFFFFF || IdxTable[fromId].Length == 0x00000000 || IdxTable[fromId].Length == 0xFFFFFFFF) { return(new T[0]); } StreamMul.Seek(IdxTable[fromId].Offset + offset, SeekOrigin.Begin); var arr = Utils.ArrayRead <T>(StreamMul, (int)count); return(arr); } else { StreamMul.Seek(_EntryOff + fromId * EntrySize + offset, SeekOrigin.Begin); var arr = Utils.ArrayRead <T>(StreamMul, (int)count); return(arr); } }
private byte[] Read(uint id) { if (id >= _EntryLength) { return(null); } //throw new ArgumentOutOfRangeException(); if (IdxTable == null) { StreamMul.Seek(_EntryOff + id * EntrySize, SeekOrigin.Begin); return(Utils.ArrayRead <byte>(StreamMul, (int)EntrySize)); } else { if (IdxTable[id].Offset == 0xFFFFFFFF || IdxTable[id].Length == 0xFFFFFFFF) { return(null); } StreamMul.Seek(IdxTable[id].Offset, SeekOrigin.Begin); return(Utils.ArrayRead <byte>(StreamMul, (int)IdxTable[id].Length)); } }
void IDataContainer.Write <T>(uint id, uint offset, T[] data, uint sfrom, uint count) { if (!StreamMul.CanWrite || (StreamIdx != null && !StreamIdx.CanWrite)) { throw new AccessViolationException(); } if (id >= _EntryLength || (IdxTable == null && data != null && Marshal.SizeOf(typeof(T)) != (EntrySize - offset) / data.Length)) { throw new ArgumentOutOfRangeException(); } if (IdxTable == null) { StreamMul.Seek(_EntryOff + id * EntrySize + offset, SeekOrigin.Begin); } else { var length = IdxTable[id].Length; IdxTable[id].Length = (uint)(offset + data.Length * Marshal.SizeOf(typeof(T))); if (IdxTable[id].Offset != 0xFFFFFFFF && length != 0xFFFFFFFF && length >= IdxTable[id].Length) { StreamMul.Seek(_EntryOff + IdxTable[id].Offset + offset, SeekOrigin.Begin); } else { StreamMul.Seek(_EntryOff + IdxTable[id].Offset, SeekOrigin.Begin); var rawdata = new byte[offset]; StreamMul.Read(rawdata, 0, (int)offset); IdxTable[id].Offset = (uint)StreamMul.Seek(0, SeekOrigin.End); StreamMul.Write(rawdata, 0, (int)offset); } StreamIdx.Seek(id * Marshal.SizeOf(typeof(IndexEntry)), SeekOrigin.Begin); Utils.ArrayWrite <IndexEntry>(StreamIdx, IdxTable, (int)id, 1); } Utils.ArrayWrite <T>(StreamMul, data, (int)sfrom, (int)count); }
void IDataContainer.Defrag() { if (StreamIdx == null || IsVirtual) { throw new MethodAccessException("Only non virtual mul containers with idx tables is possible to defrag."); } var crc32 = new Crc32(); var hash1 = new Hashtable(); var hash2 = new Hashtable(); uint eidx = 0U, fpos = 0U; var list = IdxTable.Select(e => new IndexEntry { Append = eidx++, Offset = e.Offset, Length = e.Length }).OrderBy(e => e.Offset).ToList(); var maxl = IdxTable.Max(e => ((ulong)e.Offset + (ulong)e.Length) < (ulong)StreamMul.Length ? e.Length : 0); var bufi = new byte[Math.Min(maxl << 1, StreamMul.Length)]; StreamMul.Seek(0, SeekOrigin.Begin); var back = Utils.ArrayRead <byte>(StreamMul, bufi.Length); var curleft = Console.CursorLeft; var process = Process.GetCurrentProcess(); var workset = 0U; var lastupd = 0; for (int i = 0; i < _EntryLength; ++i) { if (Environment.TickCount - lastupd > 100) { //GC.Collect(); workset = (uint)(Environment.WorkingSet >> 20); lastupd = Environment.TickCount; Console.SetCursorPosition(curleft, Console.CursorTop); Console.Write("{0,7} < {1,6:0.00}% > RAM: {2} MiB", i, (100f * i) / _EntryLength, workset); } eidx = list[i].Append; if (IdxTable[eidx].Offset == 0xFFFFFFFF || IdxTable[eidx].Length == 0x00000000 || IdxTable[eidx].Length == 0xFFFFFFFF) { continue; } var hkey = IdxTable[eidx].Offset; var hlst = hash1[hkey]; if (hlst != null) { IdxTable[eidx].Offset = IdxTable[(uint)hlst].Offset; continue; } else { hash1.Add(hkey, eidx); } if ((IdxTable[eidx].Offset + IdxTable[eidx].Length) >= back.Length) { StreamMul.Seek(IdxTable[eidx].Offset, SeekOrigin.Begin); Utils.FastRead(StreamMul, bufi, 0, (int)IdxTable[eidx].Length); } else { Array.Copy(back, IdxTable[eidx].Offset, bufi, 0, IdxTable[eidx].Length); } crc32.Reset(); crc32.Update(bufi); hkey = (uint)crc32.Value; hlst = hash2[hkey]; if (hlst != null) { var data = Read((uint)hlst); if (Utils.ArrayIdentical(data, bufi, 0, Math.Max(data.Length, (int)IdxTable[eidx].Length))) { IdxTable[eidx].Offset = IdxTable[(uint)hlst].Offset; continue; } } else { hash2.Add(hkey, eidx); } IdxTable[eidx].Offset = fpos; fpos += IdxTable[eidx].Length; StreamMul.Seek(IdxTable[eidx].Offset, SeekOrigin.Begin); Utils.ArrayWrite(StreamMul, bufi, 0, (int)IdxTable[eidx].Length); } StreamMul.SetLength(fpos); StreamMul.Flush(); FlushIdx(); }