internal Record(string name, uint dataSize, BinaryReader recordReader, TESVSnip.Domain.Data.DomainDefinition define) { this.dataSize = dataSize; int estimatedCount = Math.Max( Math.Min(16, (int)dataSize/10), 0 ); SubRecords = new AdvancedList<SubRecord>(estimatedCount) { AllowSorting = false }; Name = name; Flags1 = recordReader.ReadUInt32(); FormID = recordReader.ReadUInt32(); if (define.RecSize >= 12) Flags2 = recordReader.ReadUInt32(); if (define.RecSize >= 16) Flags3 = recordReader.ReadUInt32(); bool compressed = (Flags1 & 0x00040000) != 0; uint amountRead = 0; uint realSize = dataSize; if (compressed) { realSize = recordReader.ReadUInt32(); dataSize -= 4; } using (var stream = new MemoryStream(recordReader.ReadBytes((int)dataSize),false)) using (var br = new BinaryReader(stream)) { var dataReader = compressed ? Decompressor.Decompress(br, (int)dataSize, (int)realSize, out compressLevel) : br; { while (true) { long left = dataReader.BaseStream.Length - dataReader.BaseStream.Position; if (left < 4) { break; } string type = ReadRecName(dataReader); uint size; if (type == "XXXX") { dataReader.ReadUInt16(); size = dataReader.ReadUInt32(); type = ReadRecName(dataReader); dataReader.ReadUInt16(); } else { size = define.HEDRRecSize == 2 ? dataReader.ReadUInt16() : dataReader.ReadUInt32(); } var record = new SubRecord(this, type, dataReader, size); SubRecords.Add(record); amountRead += (uint)record.Size2; } } } if (amountRead > realSize) { Debug.Print( " * ERROR: SUB-RECORD {0} DATA DOESN'T MATCH THE SIZE SPECIFIED IN THE HEADER: DATA-SIZE={1} REAL-SIZE={2} AMOUNT-READ={3}", name, dataSize, realSize, amountRead); throw new TESParserException( string.Format( "Subrecord block did not match the size specified in the record header: ExpectedSize={0} ReadSize={1} DataSize={2}", realSize, amountRead, dataSize)); } descNameOverride = DefaultDescriptiveName; UpdateShortDescription(); // br.BaseStream.Position+=Size; }
internal GroupRecord(uint Size, BinaryReader br, TESVSnip.Domain.Data.DomainDefinition define, Func <string, bool> recFilter, bool filterAll) { Name = "GRUP"; this.data = br.ReadBytes(4); this.groupType = br.ReadUInt32(); this.dateStamp = br.ReadUInt32(); string contentType = this.groupType == 0 ? Encoding.Instance.GetString(this.data) : string.Empty; if (define.RecSize >= 16) { this.flags = br.ReadUInt32(); } uint amountRead = 0; while (amountRead < Size - (define.RecSize + 8)) { string s = ReadRecName(br); uint recsize = br.ReadUInt32(); if (s == "GRUP") { try { bool skip = filterAll || (recFilter != null && !recFilter(contentType)); var gr = new GroupRecord(recsize, br, define, recFilter, skip); if (!filterAll) { this.AddRecord(gr); } } catch (Exception e) { Alerts.Show(e.Message); } finally { amountRead += recsize; } } else { bool skip = filterAll || (recFilter != null && !recFilter(contentType)); if (skip) { long size = recsize + define.RecSize; // if ((br.ReadUInt32() & 0x00040000) > 0) size += 4; br.BaseStream.Position += size; // just read past the data amountRead += (uint)(recsize + (define.RecSize + 8)); } else { try { var r = new Record(s, recsize, br, define); this.AddRecord(r); } catch (Exception e) { Alerts.Show(e.Message); } finally { amountRead += (uint)(recsize + (define.RecSize + 8)); } } } } this.UpdateShortDescription(); if (amountRead != (Size - (define.RecSize + 8))) { throw new TESParserException( string.Format("Record block did not match the size specified in the group header! Header Size={0:D} Group Size={1:D}", Size - (define.RecSize + 8), amountRead)); } }