mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
[AMG] Implement Open and Close.
This commit is contained in:
@@ -1,10 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
|
||||
namespace Aaru.Archives;
|
||||
|
||||
public sealed partial class Amg : IArchive
|
||||
{
|
||||
List<FileEntry> _files;
|
||||
Stream _stream;
|
||||
|
||||
#region IArchive Members
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -14,14 +19,14 @@ public sealed partial class Amg : IArchive
|
||||
/// <inheritdoc />
|
||||
public string Author => Authors.NataliaPortillo;
|
||||
/// <inheritdoc />
|
||||
public bool Opened { get; }
|
||||
public bool Opened { get; private set; }
|
||||
/// <inheritdoc />
|
||||
public ArchiveSupportedFeature ArchiveFeatures => ArchiveSupportedFeature.HasEntryTimestamp |
|
||||
ArchiveSupportedFeature.SupportsCompression |
|
||||
ArchiveSupportedFeature.SupportsFilenames |
|
||||
ArchiveSupportedFeature.SupportsSubdirectories;
|
||||
/// <inheritdoc />
|
||||
public int NumberOfEntries { get; }
|
||||
public int NumberOfEntries => Opened ? _files.Count : -1;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -2,5 +2,6 @@ namespace Aaru.Archives;
|
||||
|
||||
public sealed partial class Amg
|
||||
{
|
||||
const ushort ARC_MAGIC = 0x36AD;
|
||||
const ushort ARC_MAGIC = 0x36AD;
|
||||
const ushort FILE_MAGIC = 0x1C94;
|
||||
}
|
||||
109
Aaru.Archives/Amg/Open.cs
Normal file
109
Aaru.Archives/Amg/Open.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Helpers;
|
||||
|
||||
namespace Aaru.Archives;
|
||||
|
||||
public sealed partial class Amg
|
||||
{
|
||||
#region IArchive Members
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Open(IFilter filter, Encoding encoding)
|
||||
{
|
||||
encoding ??= Encoding.ASCII;
|
||||
|
||||
if(filter.DataForkLength < Marshal.SizeOf<ArcHeader>()) return ErrorNumber.InvalidArgument;
|
||||
|
||||
_stream = filter.GetDataForkStream();
|
||||
_stream.Position = 0;
|
||||
|
||||
byte[] hdr = new byte[Marshal.SizeOf<ArcHeader>()];
|
||||
|
||||
_stream.ReadExactly(hdr, 0, hdr.Length);
|
||||
|
||||
ArcHeader header = Marshal.ByteArrayToStructureLittleEndian<ArcHeader>(hdr);
|
||||
|
||||
// Not a valid magic
|
||||
if(header.magic != ARC_MAGIC) return ErrorNumber.InvalidArgument;
|
||||
|
||||
|
||||
// Skip comment
|
||||
_stream.Position += header.commentLength;
|
||||
|
||||
int fileHeaderLen = Marshal.SizeOf<FileHeader>();
|
||||
|
||||
_files = [];
|
||||
|
||||
while(_stream.Position + fileHeaderLen < _stream.Length)
|
||||
{
|
||||
byte[] fileHdr = new byte[fileHeaderLen];
|
||||
|
||||
_stream.ReadExactly(fileHdr, 0, fileHdr.Length);
|
||||
|
||||
FileHeader fh = Marshal.ByteArrayToStructureLittleEndian<FileHeader>(fileHdr);
|
||||
|
||||
// Not a valid file magic
|
||||
if(fh.magic != FILE_MAGIC) break;
|
||||
|
||||
var entry = new FileEntry
|
||||
{
|
||||
Attributes = (FileAttributes)fh.attr,
|
||||
Compressed = (uint)(fh.compressed - fh.pathLength - fh.commentLength - fileHeaderLen),
|
||||
Crc = fh.crc,
|
||||
Flags = fh.flags,
|
||||
LastWrite = DateHandlers.DosToDateTime(fh.date, fh.time),
|
||||
Uncompressed = fh.uncompressed,
|
||||
Filename = StringHandlers.CToString(fh.filename, encoding)
|
||||
};
|
||||
|
||||
string extension = StringHandlers.CToString(fh.extension, encoding);
|
||||
|
||||
if(!string.IsNullOrEmpty(extension)) entry.Filename += "." + extension;
|
||||
|
||||
if(fh.pathLength > 0)
|
||||
{
|
||||
byte[] buffer = new byte[fh.pathLength];
|
||||
_stream.ReadExactly(buffer, 0, buffer.Length);
|
||||
string path = StringHandlers.CToString(buffer, encoding);
|
||||
path = path.Replace('\\', Path.DirectorySeparatorChar);
|
||||
entry.Filename = Path.Combine(path, entry.Filename);
|
||||
}
|
||||
|
||||
if(fh.commentLength > 0)
|
||||
{
|
||||
byte[] buffer = new byte[fh.commentLength];
|
||||
_stream.ReadExactly(buffer, 0, buffer.Length);
|
||||
entry.Comment = StringHandlers.CToString(buffer, encoding);
|
||||
}
|
||||
|
||||
entry.Offset = _stream.Position;
|
||||
|
||||
_files.Add(entry);
|
||||
|
||||
// Skip compressed data
|
||||
_stream.Position += entry.Compressed;
|
||||
}
|
||||
|
||||
Opened = true;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Close()
|
||||
{
|
||||
// Already closed
|
||||
if(!Opened) return;
|
||||
|
||||
_stream?.Close();
|
||||
_files?.Clear();
|
||||
|
||||
_stream = null;
|
||||
Opened = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Aaru.Archives;
|
||||
@@ -17,5 +19,50 @@ public sealed partial class Amg
|
||||
public readonly ushort commentLength;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nested type: FileEntry
|
||||
|
||||
struct FileEntry
|
||||
{
|
||||
public uint Uncompressed;
|
||||
public uint Compressed;
|
||||
public DateTime LastWrite;
|
||||
public FileAttributes Attributes;
|
||||
public byte Flags;
|
||||
public uint Crc;
|
||||
public string Filename;
|
||||
public string Comment;
|
||||
public long Offset;
|
||||
|
||||
public override string ToString() => Filename;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nested type: FileHeader
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
|
||||
readonly struct FileHeader
|
||||
{
|
||||
public readonly ushort magic;
|
||||
public readonly uint compressed;
|
||||
public readonly uint uncompressed;
|
||||
public readonly ushort time;
|
||||
public readonly ushort date;
|
||||
public readonly byte attr;
|
||||
public readonly byte flags;
|
||||
|
||||
// Something changes in processing when 0x80 is set
|
||||
public readonly byte unknown;
|
||||
public readonly uint crc;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
public readonly byte[] filename;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public readonly byte[] extension;
|
||||
public readonly byte pathLength;
|
||||
public readonly ushort commentLength;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.CommonTypes.Structs;
|
||||
@@ -12,15 +11,6 @@ public sealed partial class Amg
|
||||
{
|
||||
#region IArchive Members
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber Open(IFilter filter, Encoding encoding) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Close()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber GetFilename(int entryNumber, out string fileName) => throw new NotImplementedException();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user