private void ReadSectionDetails(ArchiveSectionMetadataBuilder[] sections) { #region Counts bool hasStreamCounts = false; ArchiveMetadataToken token; for (;;) { token = ReadToken(); if (token == ArchiveMetadataToken.End || token == ArchiveMetadataToken.CRC || token == ArchiveMetadataToken.Size) { break; } if (token == ArchiveMetadataToken.NumUnpackStream) { hasStreamCounts = true; foreach (var section in sections) { section.SubStreamCount = ReadNumberAsInt32(); } } else { SkipDataBlock(); } } if (!hasStreamCounts) { foreach (var section in sections) { section.SubStreamCount = 1; } } #endregion #region Sizes foreach (var section in sections) { // v3.13 was broken and wrote empty sections // v4.07 added compat code to skip empty sections if (section.SubStreamCount.Value == 0) { continue; } var remaining = section.OutputLength; var subsections = new DecodedStreamMetadata[section.SubStreamCount.Value]; for (int i = 0; i < subsections.Length - 1; i++) { if (token == ArchiveMetadataToken.Size) { var size = ReadNumberAsInt64(); if (size == 0 || size >= remaining) { throw new InvalidDataException(); } subsections[i] = new DecodedStreamMetadata(size, null); remaining -= size; } } if (remaining == 0) { throw new InvalidDataException(); } subsections[subsections.Length - 1] = new DecodedStreamMetadata(remaining, null); section.Subsections = subsections; } if (token == ArchiveMetadataToken.Size) { token = ReadToken(); } #endregion #region Checksums int requiredChecksumCount = 0; int totalChecksumCount = 0; ImmutableArray <Checksum?> .Builder checksums = null; foreach (var section in sections) { // If there is only one stream and we have a section checksum 7z doesn't store the checksum again. if (!(section.SubStreamCount == 1 && section.OutputChecksum.HasValue)) { requiredChecksumCount += section.SubStreamCount.Value; } totalChecksumCount += section.SubStreamCount.Value; } for (;;) { if (token == ArchiveMetadataToken.End) { if (checksums == null) { checksums = ImmutableArray.CreateBuilder <Checksum?>(totalChecksumCount); for (int i = 0; i < totalChecksumCount; i++) { checksums.Add(null); } } break; } else if (token == ArchiveMetadataToken.CRC) { checksums = ImmutableArray.CreateBuilder <Checksum?>(totalChecksumCount); var vector = ReadOptionalBitVector(requiredChecksumCount); int requiredChecksumIndex = 0; foreach (var section in sections) { if (section.SubStreamCount == 1 && section.OutputChecksum.HasValue) { checksums.Add(section.OutputChecksum.Value); } else { for (int i = 0; i < section.SubStreamCount; i++) { if (vector[requiredChecksumIndex++]) { checksums.Add(new Checksum(ReadInt32())); } else { checksums.Add(null); } } } } System.Diagnostics.Debug.Assert(requiredChecksumIndex == requiredChecksumCount); System.Diagnostics.Debug.Assert(checksums.Count == totalChecksumCount); } else { SkipDataBlock(); } token = ReadToken(); } #endregion }
private void ReadSectionDetails(ArchiveSectionMetadataBuilder[] sections) { #region Counts bool hasStreamCounts = false; ArchiveMetadataToken token; for (;;) { token = ReadToken(); if (token == ArchiveMetadataToken.End || token == ArchiveMetadataToken.CRC || token == ArchiveMetadataToken.Size) break; if (token == ArchiveMetadataToken.NumUnpackStream) { hasStreamCounts = true; foreach (var section in sections) section.SubStreamCount = ReadNumberAsInt32(); } else { SkipDataBlock(); } } if (!hasStreamCounts) foreach (var section in sections) section.SubStreamCount = 1; #endregion #region Sizes foreach (var section in sections) { // v3.13 was broken and wrote empty sections // v4.07 added compat code to skip empty sections if (section.SubStreamCount.Value == 0) continue; var remaining = section.OutputLength; var subsections = new DecodedStreamMetadata[section.SubStreamCount.Value]; for (int i = 0; i < subsections.Length - 1; i++) { if (token == ArchiveMetadataToken.Size) { var size = ReadNumberAsInt64(); if (size == 0 || size >= remaining) throw new InvalidDataException(); subsections[i] = new DecodedStreamMetadata(size, null); remaining -= size; } } if (remaining == 0) throw new InvalidDataException(); subsections[subsections.Length - 1] = new DecodedStreamMetadata(remaining, null); section.Subsections = subsections; } if (token == ArchiveMetadataToken.Size) token = ReadToken(); #endregion #region Checksums int requiredChecksumCount = 0; int totalChecksumCount = 0; ImmutableArray<Checksum?>.Builder checksums = null; foreach (var section in sections) { // If there is only one stream and we have a section checksum 7z doesn't store the checksum again. if (!(section.SubStreamCount == 1 && section.OutputChecksum.HasValue)) requiredChecksumCount += section.SubStreamCount.Value; totalChecksumCount += section.SubStreamCount.Value; } for (;;) { if (token == ArchiveMetadataToken.End) { if (checksums == null) { checksums = ImmutableArray.CreateBuilder<Checksum?>(totalChecksumCount); for (int i = 0; i < totalChecksumCount; i++) checksums.Add(null); } break; } else if (token == ArchiveMetadataToken.CRC) { checksums = ImmutableArray.CreateBuilder<Checksum?>(totalChecksumCount); var vector = ReadOptionalBitVector(requiredChecksumCount); int requiredChecksumIndex = 0; foreach (var section in sections) { if (section.SubStreamCount == 1 && section.OutputChecksum.HasValue) { checksums.Add(section.OutputChecksum.Value); } else { for (int i = 0; i < section.SubStreamCount; i++) { if (vector[requiredChecksumIndex++]) checksums.Add(new Checksum(ReadInt32())); else checksums.Add(null); } } } System.Diagnostics.Debug.Assert(requiredChecksumIndex == requiredChecksumCount); System.Diagnostics.Debug.Assert(checksums.Count == totalChecksumCount); } else { SkipDataBlock(); } token = ReadToken(); } #endregion }