diff --git a/GameRes/ArcFile.cs b/GameRes/ArcFile.cs index 7afc2d31..8911d4f3 100644 --- a/GameRes/ArcFile.cs +++ b/GameRes/ArcFile.cs @@ -71,48 +71,32 @@ namespace GameRes { if (entry.Size < 4) return null; - var filename = entry.Name; - var ext = new Lazy (() => Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant(), false); var file = VFS.OpenView (entry); try { uint signature = file.View.ReadUInt32 (0); - var tried = Enumerable.Empty(); - for (;;) + foreach (var impl in FormatCatalog.Instance.FindFormats (entry.Name, signature)) { - var range = FormatCatalog.Instance.LookupSignature (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) + try { - try + var arc = impl.TryOpen (file); + if (null != arc) { - var arc = impl.TryOpen (file); - if (null != 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; + file = null; // file ownership passed to ArcFile + return arc; } } - if (0 == signature) - break; - signature = 0; - tried = range; + 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, entry.Name, X.Message)); + FormatCatalog.Instance.LastError = X; + } } } finally diff --git a/GameRes/Audio.cs b/GameRes/Audio.cs index 1e9a0e14..9424b5f2 100644 --- a/GameRes/Audio.cs +++ b/GameRes/Audio.cs @@ -171,27 +171,23 @@ namespace GameRes public static SoundInput Read (IBinaryStream file) { - uint signature = file.Signature; - for (;;) + foreach (var impl in FormatCatalog.Instance.FindFormats (file.Name, file.Signature)) { - var range = FormatCatalog.Instance.LookupSignature (signature); - foreach (var impl in range) + try { - try - { - file.Position = 0; - SoundInput sound = impl.TryOpen (file); - if (null != sound) - return sound; - } - catch (System.Exception X) - { - FormatCatalog.Instance.LastError = X; - } + file.Position = 0; + SoundInput sound = impl.TryOpen (file); + if (null != sound) + return sound; + } + catch (OperationCanceledException) + { + throw; + } + catch (System.Exception X) + { + FormatCatalog.Instance.LastError = X; } - if (0 == signature) - break; - signature = 0; } return null; } diff --git a/GameRes/FormatCatalog.cs b/GameRes/FormatCatalog.cs index 8e866c64..8c5e1b62 100644 --- a/GameRes/FormatCatalog.cs +++ b/GameRes/FormatCatalog.cs @@ -163,6 +163,32 @@ namespace GameRes return LookupSignature (signature).OfType(); } + /// + /// Enumerate resources matching specified and filename extension. + /// + internal IEnumerable FindFormats (string filename, uint signature) where ResourceType : IResource + { + var ext = new Lazy (() => Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant(), false); + var tried = Enumerable.Empty(); + for (;;) + { + var range = LookupSignature (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; + } + } + /// /// Create GameRes.Entry corresponding to extension. /// May be thrown if filename contains invalid diff --git a/GameRes/Image.cs b/GameRes/Image.cs index 6a9e5d73..1773ec93 100644 --- a/GameRes/Image.cs +++ b/GameRes/Image.cs @@ -131,37 +131,23 @@ namespace GameRes public static System.Tuple FindFormat (IBinaryStream file) { - uint signature = file.Signature; - Lazy ext = null; - if (!string.IsNullOrEmpty (file.Name)) - ext = new Lazy (() => Path.GetExtension (file.Name).TrimStart ('.').ToLowerInvariant(), false); - for (;;) + foreach (var impl in FormatCatalog.Instance.FindFormats (file.Name, file.Signature)) { - var range = FormatCatalog.Instance.LookupSignature (signature); - // 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 { - try + file.Position = 0; + ImageMetaData metadata = impl.ReadMetaData (file); + if (null != metadata) { - file.Position = 0; - ImageMetaData metadata = impl.ReadMetaData (file); - if (null != metadata) - { - metadata.FileName = file.Name; - return Tuple.Create (impl, metadata); - } + metadata.FileName = file.Name; + return Tuple.Create (impl, metadata); } - catch (OperationCanceledException) - { - throw; - } - catch { } } - if (0 == signature) - break; - signature = 0; + catch (OperationCanceledException) + { + throw; + } + catch { } } return null; }