XZIndex.cs 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using SharpCompress.IO;
  7. namespace SharpCompress.Compressors.Xz
  8. {
  9. [CLSCompliant(false)]
  10. public class XZIndex
  11. {
  12. private readonly BinaryReader _reader;
  13. public long StreamStartPosition { get; private set; }
  14. public ulong NumberOfRecords { get; private set; }
  15. public List<XZIndexRecord> Records { get; } = new List<XZIndexRecord>();
  16. private readonly bool _indexMarkerAlreadyVerified;
  17. public XZIndex(BinaryReader reader, bool indexMarkerAlreadyVerified)
  18. {
  19. _reader = reader;
  20. _indexMarkerAlreadyVerified = indexMarkerAlreadyVerified;
  21. StreamStartPosition = reader.BaseStream.Position;
  22. if (indexMarkerAlreadyVerified)
  23. StreamStartPosition--;
  24. }
  25. public static XZIndex FromStream(Stream stream, bool indexMarkerAlreadyVerified)
  26. {
  27. var index = new XZIndex(new BinaryReader(new NonDisposingStream(stream), Encoding.UTF8), indexMarkerAlreadyVerified);
  28. index.Process();
  29. return index;
  30. }
  31. public void Process()
  32. {
  33. if (!_indexMarkerAlreadyVerified)
  34. VerifyIndexMarker();
  35. NumberOfRecords = _reader.ReadXZInteger();
  36. for (ulong i = 0; i < NumberOfRecords; i++)
  37. {
  38. Records.Add(XZIndexRecord.FromBinaryReader(_reader));
  39. }
  40. SkipPadding();
  41. VerifyCrc32();
  42. }
  43. private void VerifyIndexMarker()
  44. {
  45. byte marker = _reader.ReadByte();
  46. if (marker != 0)
  47. throw new InvalidDataException("Not an index block");
  48. }
  49. private void SkipPadding()
  50. {
  51. int bytes = (int)(_reader.BaseStream.Position - StreamStartPosition) % 4;
  52. if (bytes > 0)
  53. {
  54. byte[] paddingBytes = _reader.ReadBytes(4 - bytes);
  55. if (paddingBytes.Any(b => b != 0))
  56. throw new InvalidDataException("Padding bytes were non-null");
  57. }
  58. }
  59. private void VerifyCrc32()
  60. {
  61. uint crc = _reader.ReadLittleEndianUInt32();
  62. // TODO verify this matches
  63. }
  64. }
  65. }