(FormatCatalog.FindFormats): new generic method.

This commit is contained in:
morkt 2016-12-17 18:51:33 +04:00
parent 7c989a0150
commit f3e3446c9a
4 changed files with 69 additions and 77 deletions

View File

@ -71,48 +71,32 @@ namespace GameRes
{ {
if (entry.Size < 4) if (entry.Size < 4)
return null; return null;
var filename = entry.Name;
var ext = new Lazy<string> (() => Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant(), false);
var file = VFS.OpenView (entry); var file = VFS.OpenView (entry);
try try
{ {
uint signature = file.View.ReadUInt32 (0); uint signature = file.View.ReadUInt32 (0);
var tried = Enumerable.Empty<ArchiveFormat>(); foreach (var impl in FormatCatalog.Instance.FindFormats<ArchiveFormat> (entry.Name, signature))
for (;;)
{ {
var range = FormatCatalog.Instance.LookupSignature<ArchiveFormat> (signature); try
if (tried.Any())
range = range.Except (tried);
// check formats that match filename extension first
if (range.Skip(1).Any()) // if range.Count() > 1
range = range.OrderByDescending (f => f.Extensions.Any (e => e == ext.Value));
foreach (var impl in range)
{ {
try var arc = impl.TryOpen (file);
if (null != arc)
{ {
var arc = impl.TryOpen (file); file = null; // file ownership passed to ArcFile
if (null != arc) return arc;
{
file = null; // file ownership passed to ArcFile
return arc;
}
}
catch (OperationCanceledException X)
{
FormatCatalog.Instance.LastError = X;
return null;
}
catch (Exception X)
{
// ignore failed open attmepts
Trace.WriteLine (string.Format ("[{0}] {1}: {2}", impl.Tag, filename, X.Message));
FormatCatalog.Instance.LastError = X;
} }
} }
if (0 == signature) catch (OperationCanceledException X)
break; {
signature = 0; FormatCatalog.Instance.LastError = X;
tried = range; return null;
}
catch (Exception X)
{
// ignore failed open attmepts
Trace.WriteLine (string.Format ("[{0}] {1}: {2}", impl.Tag, entry.Name, X.Message));
FormatCatalog.Instance.LastError = X;
}
} }
} }
finally finally

View File

@ -171,27 +171,23 @@ namespace GameRes
public static SoundInput Read (IBinaryStream file) public static SoundInput Read (IBinaryStream file)
{ {
uint signature = file.Signature; foreach (var impl in FormatCatalog.Instance.FindFormats<AudioFormat> (file.Name, file.Signature))
for (;;)
{ {
var range = FormatCatalog.Instance.LookupSignature<AudioFormat> (signature); try
foreach (var impl in range)
{ {
try file.Position = 0;
{ SoundInput sound = impl.TryOpen (file);
file.Position = 0; if (null != sound)
SoundInput sound = impl.TryOpen (file); return sound;
if (null != sound) }
return sound; catch (OperationCanceledException)
} {
catch (System.Exception X) throw;
{ }
FormatCatalog.Instance.LastError = X; catch (System.Exception X)
} {
FormatCatalog.Instance.LastError = X;
} }
if (0 == signature)
break;
signature = 0;
} }
return null; return null;
} }

View File

@ -163,6 +163,32 @@ namespace GameRes
return LookupSignature (signature).OfType<Type>(); return LookupSignature (signature).OfType<Type>();
} }
/// <summary>
/// Enumerate resources matching specified <paramref name="signature"/> and filename extension.
/// </summary>
internal IEnumerable<ResourceType> FindFormats<ResourceType> (string filename, uint signature) where ResourceType : IResource
{
var ext = new Lazy<string> (() => Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant(), false);
var tried = Enumerable.Empty<ResourceType>();
for (;;)
{
var range = LookupSignature<ResourceType> (signature);
if (tried.Any())
range = range.Except (tried);
// check formats that match filename extension first
if (range.Skip (1).Any()) // if range.Count() > 1
range = range.OrderByDescending (f => f.Extensions.Any (e => e == ext.Value));
foreach (var impl in range)
{
yield return impl;
}
if (0 == signature)
break;
signature = 0;
tried = range;
}
}
/// <summary> /// <summary>
/// Create GameRes.Entry corresponding to <paramref name="filename"/> extension. /// Create GameRes.Entry corresponding to <paramref name="filename"/> extension.
/// <exception cref="System.ArgumentException">May be thrown if filename contains invalid /// <exception cref="System.ArgumentException">May be thrown if filename contains invalid

View File

@ -131,37 +131,23 @@ namespace GameRes
public static System.Tuple<ImageFormat, ImageMetaData> FindFormat (IBinaryStream file) public static System.Tuple<ImageFormat, ImageMetaData> FindFormat (IBinaryStream file)
{ {
uint signature = file.Signature; foreach (var impl in FormatCatalog.Instance.FindFormats<ImageFormat> (file.Name, file.Signature))
Lazy<string> ext = null;
if (!string.IsNullOrEmpty (file.Name))
ext = new Lazy<string> (() => Path.GetExtension (file.Name).TrimStart ('.').ToLowerInvariant(), false);
for (;;)
{ {
var range = FormatCatalog.Instance.LookupSignature<ImageFormat> (signature); try
// check formats that match filename extension first
if (ext != null && range.Skip(1).Any())
range = range.OrderByDescending (f => f.Extensions.Any (e => e == ext.Value));
foreach (var impl in range)
{ {
try file.Position = 0;
ImageMetaData metadata = impl.ReadMetaData (file);
if (null != metadata)
{ {
file.Position = 0; metadata.FileName = file.Name;
ImageMetaData metadata = impl.ReadMetaData (file); return Tuple.Create (impl, metadata);
if (null != metadata)
{
metadata.FileName = file.Name;
return Tuple.Create (impl, metadata);
}
} }
catch (OperationCanceledException)
{
throw;
}
catch { }
} }
if (0 == signature) catch (OperationCanceledException)
break; {
signature = 0; throw;
}
catch { }
} }
return null; return null;
} }