public new Dictionary <int, byte[]> ReadOffsetData(BinaryReader dbReader, long pos) { Dictionary <int, byte[]> CopyTable = new Dictionary <int, byte[]>(); List <Tuple <int, short> > offsetmap = new List <Tuple <int, short> >(); Dictionary <int, OffsetDuplicate> firstindex = new Dictionary <int, OffsetDuplicate>(); long commonDataTablePos = dbReader.BaseStream.Length - CommonDataTableSize; long copyTablePos = commonDataTablePos - CopyTableSize; long indexTablePos = copyTablePos - (HasIndexTable ? RecordCount * 4 : 0); int[] m_indexes = null; //Offset Map if (HasOffsetTable) { // Records table dbReader.Scrub(StringBlockSize); for (int i = 0; i < (MaxId - MinId + 1); i++) { int offset = dbReader.ReadInt32(); short length = dbReader.ReadInt16(); if (offset == 0 || length == 0) { continue; } //Special case, may contain duplicates in the offset map that we don't want if (CopyTableSize == 0) { if (!firstindex.ContainsKey(offset)) { firstindex.Add(offset, new OffsetDuplicate(offsetmap.Count, firstindex.Count)); } else { OffsetDuplicates.Add(MinId + i, firstindex[offset].VisibleIndex); } } offsetmap.Add(new Tuple <int, short>(offset, length)); } } //Index table if (HasIndexTable) { //Offset map alone reads straight into this others may not if (!HasOffsetTable || HasSecondIndex) { dbReader.Scrub(indexTablePos); } m_indexes = new int[RecordCount]; for (int i = 0; i < RecordCount; i++) { m_indexes[i] = dbReader.ReadInt32(); } } //Extract record data for (int i = 0; i < Math.Max(RecordCount, offsetmap.Count); i++) { if (HasOffsetTable) { int id = m_indexes[CopyTable.Count]; var map = offsetmap[i]; if (CopyTableSize == 0 && firstindex[map.Item1].HiddenIndex != i) //Ignore duplicates { continue; } dbReader.Scrub(map.Item1); IEnumerable <byte> recordbytes = BitConverter.GetBytes(id) .Concat(dbReader.ReadBytes(map.Item2)); CopyTable.Add(id, recordbytes.ToArray()); } else { dbReader.Scrub(pos + i * RecordSize); byte[] recordbytes = dbReader.ReadBytes((int)RecordSize).ToArray(); if (HasIndexTable) { IEnumerable <byte> newrecordbytes = BitConverter.GetBytes(m_indexes[i]).Concat(recordbytes); CopyTable.Add(m_indexes[i], newrecordbytes.ToArray()); } else { int bytecount = FieldStructure[IdIndex].ByteCount; int offset = FieldStructure[IdIndex].Offset; int id = 0; for (int j = 0; j < bytecount; j++) { id |= (recordbytes[offset + j] << (j * 8)); } CopyTable.Add(id, recordbytes); } } } //CopyTable if (CopyTableSize != 0 && copyTablePos != dbReader.BaseStream.Length) { dbReader.Scrub(copyTablePos); while (dbReader.BaseStream.Position != dbReader.BaseStream.Length) { int id = dbReader.ReadInt32(); int idcopy = dbReader.ReadInt32(); byte[] copyRow = CopyTable[idcopy]; byte[] newRow = new byte[copyRow.Length]; Array.Copy(copyRow, newRow, newRow.Length); Array.Copy(BitConverter.GetBytes(id), newRow, sizeof(int)); CopyTable.Add(id, newRow); } } //CommonDataTable if (CommonDataTableSize > 0) { dbReader.Scrub(commonDataTablePos); int columncount = dbReader.ReadInt32(); var commondatalookup = new Dictionary <int, byte[]> [columncount]; //Initial Data extraction for (int i = 0; i < columncount; i++) { int count = dbReader.ReadInt32(); byte type = dbReader.ReadByte(); short bit = CommonDataBits[type]; int size = (32 - bit) >> 3; commondatalookup[i] = new Dictionary <int, byte[]>(); //New field not defined in header if (i > FieldStructure.Count - 1) { var offset = (ushort)((FieldStructure.Count == 0 ? 0 : FieldStructure[i - 1].Offset + FieldStructure[i - 1].ByteCount)); FieldStructure.Add(new FieldStructureEntry(bit, offset, type)); if (FieldStructure.Count > 1) { FieldStructure[i - 1].SetLength(FieldStructure[i]); } } for (int x = 0; x < count; x++) { commondatalookup[i].Add(dbReader.ReadInt32(), dbReader.ReadBytes(size)); } } var ids = CopyTable.Keys.ToArray(); foreach (var id in ids) { for (int i = 0; i < commondatalookup.Length; i++) { if (!FieldStructure[i].CommonDataColumn) { continue; } var col = commondatalookup[i]; var defaultValue = TableStructure?.Fields?[i]?.DefaultValue; defaultValue = string.IsNullOrEmpty(defaultValue) ? "0" : defaultValue; var field = FieldStructure[i]; var zeroData = new byte[field.ByteCount]; if (defaultValue != "0") { switch (field.CommonDataType) { case 1: zeroData = BitConverter.GetBytes(ushort.Parse(defaultValue)); break; case 2: zeroData = new[] { byte.Parse(defaultValue) }; break; case 3: zeroData = BitConverter.GetBytes(float.Parse(defaultValue)); break; case 4: zeroData = BitConverter.GetBytes(int.Parse(defaultValue)); break; } } byte[] currentData = CopyTable[id]; byte[] data = col.ContainsKey(id) ? col[id] : zeroData; Array.Resize(ref currentData, currentData.Length + data.Length); Array.Copy(data, 0, currentData, field.Offset, data.Length); CopyTable[id] = currentData; } } commondatalookup = null; RawRecordSize = (uint)CopyTable.Values.First().Length; } return(CopyTable); }
public Dictionary <int, byte[]> ReadOffsetData(BinaryReader dbReader, long pos) { Dictionary <int, byte[]> CopyTable = new Dictionary <int, byte[]>(); List <Tuple <int, short> > offsetmap = new List <Tuple <int, short> >(); Dictionary <int, OffsetDuplicate> firstindex = new Dictionary <int, OffsetDuplicate>(); long copyTablePos = dbReader.BaseStream.Length - CopyTableSize; long indexTablePos = copyTablePos - (HasIndexTable ? RecordCount * 4 : 0); int[] m_indexes = null; //Offset Map if (HasOffsetTable) { // Records table dbReader.Scrub(StringBlockSize); for (int i = 0; i < (MaxId - MinId + 1); i++) { int offset = dbReader.ReadInt32(); short length = dbReader.ReadInt16(); if (offset == 0 || length == 0) { continue; } //Special case, may contain duplicates in the offset map that we don't want if (CopyTableSize == 0) { if (!firstindex.ContainsKey(offset)) { firstindex.Add(offset, new OffsetDuplicate(offsetmap.Count, firstindex.Count)); } else { OffsetDuplicates.Add(MinId + i, firstindex[offset].VisibleIndex); } } offsetmap.Add(new Tuple <int, short>(offset, length)); } } if (HasRelationshipData) { dbReader.BaseStream.Position += (MaxId - MinId + 1) * 4; } //Index table if (HasIndexTable) { //Offset map alone reads straight into this others may not if (!HasOffsetTable || HasRelationshipData) { dbReader.Scrub(indexTablePos); } m_indexes = new int[RecordCount]; for (int i = 0; i < RecordCount; i++) { m_indexes[i] = dbReader.ReadInt32(); } } //Extract record data for (int i = 0; i < Math.Max(RecordCount, offsetmap.Count); i++) { if (HasOffsetTable) { int id = m_indexes[CopyTable.Count]; var map = offsetmap[i]; if (CopyTableSize == 0 && firstindex[map.Item1].HiddenIndex != i) //Ignore duplicates { continue; } dbReader.Scrub(map.Item1); IEnumerable <byte> recordbytes = BitConverter.GetBytes(id).Concat(dbReader.ReadBytes(map.Item2)); CopyTable.Add(id, recordbytes.ToArray()); } else { dbReader.Scrub(pos + i * RecordSize); byte[] recordbytes = dbReader.ReadBytes((int)RecordSize); if (HasIndexTable) { IEnumerable <byte> newrecordbytes = BitConverter.GetBytes(m_indexes[i]).Concat(recordbytes); CopyTable.Add(m_indexes[i], newrecordbytes.ToArray()); } else { int bytecount = FieldStructure[IdIndex].ByteCount; int offset = FieldStructure[IdIndex].Offset; int id = 0; for (int j = 0; j < bytecount; j++) { id |= (recordbytes[offset + j] << (j * 8)); } CopyTable.Add(id, recordbytes); } } } //CopyTable if (CopyTableSize != 0 && copyTablePos != dbReader.BaseStream.Length) { dbReader.Scrub(copyTablePos); while (dbReader.BaseStream.Position != dbReader.BaseStream.Length) { int id = dbReader.ReadInt32(); int idcopy = dbReader.ReadInt32(); byte[] copyRow = CopyTable[idcopy]; byte[] newRow = new byte[copyRow.Length]; Array.Copy(copyRow, newRow, newRow.Length); Array.Copy(BitConverter.GetBytes(id), newRow, sizeof(int)); CopyTable.Add(id, newRow); } } return(CopyTable); }