ArchiveZZZ.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. namespace OpenVIII
  7. {
  8. public class ArchiveZZZ : ArchiveBase
  9. {
  10. public override ArchiveBase GetArchive(Memory.Archive archive)
  11. {
  12. return new ArchiveWorker(GetBinaryFile(archive.FI), GetBinaryFile(archive.FS), GetBinaryFile(archive.FL));
  13. }
  14. public override byte[] GetBinaryFile(string fileName, bool cache = false)
  15. {
  16. fileName = headerData.GetFilenames().FirstOrDefault(x => x.IndexOf(fileName, StringComparison.OrdinalIgnoreCase) >= 0);
  17. if (string.IsNullOrWhiteSpace(fileName)) return null;
  18. FileData filedata = headerData.First(x => x.Filename == fileName);
  19. using (BinaryReader br = new BinaryReader(new FileStream(archive.ZZZ, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
  20. {
  21. br.BaseStream.Seek(filedata.Offset, SeekOrigin.Begin);
  22. return br.ReadBytes(checked((int)filedata.Size));
  23. }
  24. }
  25. //public Stream GetBinaryFileStream(string fileName, bool cache = false)
  26. //{
  27. //}
  28. public override string[] GetListOfFiles() => headerData?.GetFilenames().ToArray();
  29. public override Memory.Archive GetPath() => archive;
  30. private Memory.Archive archive;
  31. private Header headerData;
  32. private struct FileData
  33. {
  34. public string Filename { get; set; }
  35. public long Offset { get; set; }
  36. public uint Size { get; set; }
  37. /// <summary>
  38. /// Decode/Encode the filename string as bytes.
  39. /// </summary>
  40. /// <remarks>
  41. /// Could be Ascii or UTF8, I see no special characters and the first like 127 of UTF8 is the
  42. /// same as Ascii.
  43. /// </remarks>
  44. private static string ConvertFilename(byte[] filenamebytes) => System.Text.Encoding.UTF8.GetString(filenamebytes);
  45. public static FileData Load(BinaryReader br)
  46. {
  47. int FilenameLength = br.ReadInt32();
  48. byte[] Filenamebytes = br.ReadBytes(FilenameLength);
  49. return new FileData
  50. {
  51. Offset = br.ReadInt64(),
  52. Size = br.ReadUInt32(),
  53. Filename = ConvertFilename(Filenamebytes)
  54. };
  55. }
  56. }
  57. private class Header : IList<FileData>
  58. {
  59. private Header(int count) => Data = new List<FileData>(count);
  60. private List<FileData> Data;
  61. public FileData this[int index] { get => ((IList<FileData>)Data)[index]; set => ((IList<FileData>)Data)[index] = value; }
  62. public bool IsReadOnly => ((IList<FileData>)Data).IsReadOnly;
  63. int ICollection<FileData>.Count => ((IList<FileData>)Data).Count;
  64. public void Add(FileData item) => ((IList<FileData>)Data).Add(item);
  65. public void Clear() => ((IList<FileData>)Data).Clear();
  66. public bool Contains(FileData item) => ((IList<FileData>)Data).Contains(item);
  67. public void CopyTo(FileData[] array, int arrayIndex) => ((IList<FileData>)Data).CopyTo(array, arrayIndex);
  68. public IEnumerator<FileData> GetEnumerator() => ((IList<FileData>)Data).GetEnumerator();
  69. public int IndexOf(FileData item) => ((IList<FileData>)Data).IndexOf(item);
  70. public void Insert(int index, FileData item) => ((IList<FileData>)Data).Insert(index, item);
  71. public bool Remove(FileData item) => ((IList<FileData>)Data).Remove(item);
  72. public void RemoveAt(int index) => ((IList<FileData>)Data).RemoveAt(index);
  73. IEnumerator IEnumerable.GetEnumerator() => ((IList<FileData>)Data).GetEnumerator();
  74. public static Header Load(BinaryReader br)
  75. {
  76. Header r = new Header(br.ReadInt32());
  77. for (int i = 0; i < r.Data.Capacity; i++)
  78. r.Data.Add(FileData.Load(br));
  79. return r;
  80. }
  81. public IOrderedEnumerable<string> GetFilenames()
  82. => Data.Select(x => x.Filename).OrderBy(x => x.Length).ThenBy(x => x, StringComparer.OrdinalIgnoreCase);
  83. private Header() => Data = new List<FileData>();
  84. }
  85. }
  86. }