Skip to content

Commit

Permalink
Refactor data header entries
Browse files Browse the repository at this point in the history
  • Loading branch information
DaZombieKiller committed Mar 12, 2024
1 parent 712b0cf commit 18d5133
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 173 deletions.
101 changes: 0 additions & 101 deletions tools/TLTool/DataHeader.InternalHeaderEntry.cs

This file was deleted.

29 changes: 13 additions & 16 deletions tools/TLTool/DataHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public sealed partial class DataHeader
public DateTime CreationTime { get; set; } = DateTime.UtcNow;

/// <summary>The entries contained in the <see cref="DataHeader"/>.</summary>
public Dictionary<uint, IDataHeaderEntry> Entries { get; } = [];
public Dictionary<uint, DataHeaderEntry> Entries { get; } = [];

/// <summary>Reads the entries from the specified stream into the <see cref="DataHeader"/>.</summary>
/// <param name="data">The data file containing the data for the entries described in the stream.</param>
Expand All @@ -34,35 +34,32 @@ public void ReadFrom(BinaryReader reader, FileInfo data, bool is32Bit)
{
reader.ReadUInt32();
var file = files[reader.ReadUInt32()];
Entries.Add(file.Hash, new InternalHeaderEntry(data, Encoding.ASCII.GetString(file.Extension))
{
Offset = (long)file.Offset,
Length = (long)file.Length,
CompressedLength = (long)file.CompressedLength,
});
var source = new TLFileDataSource(data, (long)file.Offset, (long)file.Length, (long)file.CompressedLength);
var entry = new DataHeaderEntry(source, Encoding.ASCII.GetString(file.Extension));
Entries.Add(file.Hash, entry);
}
}

/// <summary>Adds the specified file to the <see cref="DataHeader"/>.</summary>
public void AddFile(string name, IDataHeaderEntry entry)
public void AddFile(string name, DataHeaderEntry entry)
{
AddFile(NameHash.Compute(name), entry);
}

/// <summary>Adds the specified file to the <see cref="DataHeader"/>.</summary>
public void AddFile(uint hash, IDataHeaderEntry entry)
public void AddFile(uint hash, DataHeaderEntry entry)
{
Entries.Add(hash, entry);
}

/// <summary>Adds the specified file to the <see cref="DataHeader"/>.</summary>
public void AddOrUpdateFile(string name, IDataHeaderEntry entry)
public void AddOrUpdateFile(string name, DataHeaderEntry entry)
{
AddOrUpdateFile(NameHash.Compute(name), entry);
}

/// <summary>Adds the specified file to the <see cref="DataHeader"/>.</summary>
public void AddOrUpdateFile(uint hash, IDataHeaderEntry entry)
public void AddOrUpdateFile(uint hash, DataHeaderEntry entry)
{
Entries[hash] = entry;
}
Expand All @@ -78,7 +75,7 @@ public unsafe void Write(BinaryWriter writer, Stream data, bool is32Bit)

// The entries array is sorted by hash so that the engine can perform a binary search on it.
var entries = Entries.ToArray();
Array.Sort(entries, new KeyComparer<uint, IDataHeaderEntry>());
Array.Sort(entries, new KeyComparer<uint, DataHeaderEntry>());

header.FileHashArrayOffset = (ulong)writer.BaseStream.Position - (ulong)RawHeader.GetBaseEntryOffset(is32Bit);
header.FileHashArrayLength = (uint)entries.Length;
Expand All @@ -98,8 +95,8 @@ public unsafe void Write(BinaryWriter writer, Stream data, bool is32Bit)
{
Hash = hash,
Offset = (ulong)data.Position,
Length = (ulong)entry.Length,
CompressedLength = (ulong)entry.Length,
Length = (ulong)entry.DataSource.Length,
CompressedLength = (ulong)entry.DataSource.Length,
};

fixed (char* extension = entry.Extension)
Expand All @@ -114,15 +111,15 @@ public unsafe void Write(BinaryWriter writer, Stream data, bool is32Bit)
file.ExtensionLength = (byte)length;
}

if (entry is InternalHeaderEntry internalEntry)
if (entry.DataSource is TLFileDataSource internalEntry)
{
file.CompressedLength = (ulong)internalEntry.CompressedLength;
file.Offset = (ulong)internalEntry.Offset;
file.Write(writer);
continue;
}

using (var stream = entry.OpenRead())
using (var stream = entry.DataSource.OpenRead())
stream.CopyTo(data);

file.Write(writer);
Expand Down
33 changes: 20 additions & 13 deletions tools/TLTool/DataHeaderEntry.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
namespace TLTool;

/// <summary>A data header entry referencing an external file.</summary>
public sealed class DataHeaderEntry : IDataHeaderEntry
/// <summary>An entry in a data file header.</summary>
public sealed class DataHeaderEntry
{
/// <summary>The file used as the source for the entry's data.</summary>
public FileInfo FileInfo { get; }
/// <summary>The source for the entry's data.</summary>
public IDataSource DataSource { get; }

/// <inheritdoc/>
public long Length => FileInfo.Length;

/// <inheritdoc/>
public string Extension => FileInfo.Extension.TrimStart('.');
/// <summary>The file extension for the entry, excluding a leading period.</summary>
public string Extension { get; }

/// <summary>Initializes a new <see cref="DataHeaderEntry"/> instance.</summary>
public DataHeaderEntry(FileInfo file)
{
ArgumentNullException.ThrowIfNull(file);
FileInfo = file;
DataSource = new FileDataSource(file);
Extension = GetExtension(file.Extension);

static string GetExtension(string extension)
{
if (string.IsNullOrEmpty(extension))
return extension;

return extension[1..];
}
}

/// <inheritdoc/>
public Stream OpenRead()
/// <summary>Initializes a new <see cref="DataHeaderEntry"/> instance.</summary>
public DataHeaderEntry(IDataSource source, string extension)
{
return FileInfo.OpenRead();
DataSource = source;
Extension = extension;
}
}
24 changes: 24 additions & 0 deletions tools/TLTool/FileDataSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace TLTool;

/// <summary>A data source referencing a file on disk.</summary>
public sealed class FileDataSource : IDataSource
{
/// <summary>The file referenced by this data source.</summary>
public FileInfo File { get; }

/// <inheritdoc/>
public long Length => File.Length;

/// <summary>Initializes a new <see cref="FileDataSource"/> instance.</summary>
public FileDataSource(FileInfo file)
{
ArgumentNullException.ThrowIfNull(file);
File = file;
}

/// <inheritdoc/>
public Stream OpenRead()
{
return File.OpenRead();
}
}
14 changes: 0 additions & 14 deletions tools/TLTool/IDataHeaderEntry.cs

This file was deleted.

11 changes: 11 additions & 0 deletions tools/TLTool/IDataSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace TLTool;

/// <summary>A source of data.</summary>
public interface IDataSource
{
/// <summary>The uncompressed length of the data, in bytes.</summary>
long Length { get; }

/// <summary>Opens the data for reading.</summary>
Stream OpenRead();
}
34 changes: 34 additions & 0 deletions tools/TLTool/NameDictionary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace TLTool;

public sealed class NameDictionary : Dictionary<uint, string>
{
public bool TryAdd(string name)
{
return TryAdd(NameHash.Compute(name), name);
}

public string GetNameOrFallback(uint hash, string extension)
{
if (TryGetValue(hash, out string? name))
return name;

return $"${hash:X8}.{extension}";
}

public void AddNames(TextReader reader)
{
for (string? line; (line = reader.ReadLine()) is { };)
{
if (string.IsNullOrEmpty(line))
continue;

TryAdd(line);
}
}

public void AddNamesFromFile(string path)
{
using var reader = new StreamReader(path);
AddNames(reader);
}
}
2 changes: 1 addition & 1 deletion tools/TLTool/PackCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void Execute(InvocationContext context)

if (header.Entries.TryGetValue(hash, out var entry))
{
Console.WriteLine($"Error: cannot import '{file}' because it conflicts with '{((DataHeaderEntry)entry).FileInfo.FullName}'.");
Console.WriteLine($"Error: cannot import '{file}' because it conflicts with '{((FileDataSource)entry.DataSource).File.FullName}'.");
continue;
}

Expand Down
Loading

0 comments on commit 18d5133

Please sign in to comment.