/// <summary> /// Gets the file extension(s) commonly used for the given compressed archive format. /// </summary> /// <param name="format">The compressed archive format whose file extensions are desired.</param> /// <returns>The file extensions. If an unexpected value for <paramref name="format"/> is provided, an empty enumerable is returned.</returns> public static IEnumerable <string> FileExtensions(this CompressedArchiveFormat format) { lock (Lock) { var fileExtensions = Enumerable.Empty <string>(); List <string> registeredFileExtensions; if (format.IsCompressedArchiveFormatSupported() && CompressedArchiveFormatFileExtensions.Value.TryGetValue(format, out registeredFileExtensions)) { fileExtensions = registeredFileExtensions; } return(fileExtensions); } }
/// <summary> /// Registers a <see cref="CompressedArchiveFormat"/> for use. /// </summary> /// <param name="format">The format to register.</param> /// <param name="fileExtensions">The file extensions to associate with <paramref name="format"/>.</param> /// <param name="implementations">The implementations to associate with <paramref name="format"/>.</param> /// <returns><c>true</c> if <paramref name="format"/> was newly registered, <c>false</c> otherwise.</returns> /// <remarks>If this method is called multiple times with the same <paramref name="format"/> and other arguments, no net effect results. If it is /// called with values in the <paramref name="fileExtensions"/> and <paramref name="implementations"/> arguments that are not already associated /// with <paramref name="format"/>, they will be added, subject to the restrictions documented in the <see cref="AddFileExtension(CompressedArchiveFormat, string, bool)"/> /// and <see cref="AddImplementation(CompressedArchiveFormat, CompressedArchiveAccessImplementation, bool)"/> methods respectively. Note that in this /// usage, the default / preferred file extension and implementation will not be changed.</remarks> public static bool RegisterCompressedArchiveFormat(this CompressedArchiveFormat format, IEnumerable <string> fileExtensions, IEnumerable <CompressedArchiveAccessImplementation> implementations) { if (format == CompressedArchiveFormat.None) { throw new ArgumentOutOfRangeException("format"); } if (fileExtensions == null) { throw new ArgumentNullException("fileExtensions"); } if (!fileExtensions.Any()) { throw new ArgumentException(Resources.Strings.CompressedArchiveFormat_FileExtensionRequiredError, "fileExtensions"); } if (implementations == null) { throw new ArgumentNullException("implementations"); } if (!implementations.Any()) { throw new ArgumentException(Resources.Strings.CompressedArchiveFormat_ImplementationRequired, "implementations"); } lock (Lock) { if (!CompressedArchiveFormatFileExtensions.Value.Keys.Contains(format)) { CompressedArchiveFormatFileExtensions.Value[format] = new List <string>(); } } foreach (var fileExtension in fileExtensions) { format.AddFileExtension(fileExtension, makeDefault: false); } lock (Lock) { if (!CompressedArchiveAccessImplementations.Value.Keys.Contains(format)) { CompressedArchiveAccessImplementations.Value[format] = new List <CompressedArchiveAccessImplementation>(); } } foreach (var implementation in implementations) { format.AddImplementation(implementation, makePreferred: false); } var registered = AvailableFormats.Add(format); return(registered); }
private static bool FormatMustBeExtracted(CompressedArchiveFormat format) { var requiresExtraction = false; switch (format) { case CompressedArchiveFormat.GZip: // GZIP streams must be extracted. requiresExtraction = true; break; default: break; } return(requiresExtraction); }
/// <summary> /// Register a factory method for a specific implementation and type of compressed archive access type. /// </summary> /// <param name="format">The format for which the factory is being registered.</param> /// <param name="implementation">The implementation for which the factory is being registered.</param> /// <param name="factory">The factory method.</param> /// <returns><c>true</c> if the factory was successfully registered; <c>false</c> otherwise.</returns> /// <exception cref="System.ArgumentOutOfRangeException">Thrown if the value of <paramref name="format"/> or <paramref name="implementation"/> is not valid.</exception> public static bool RegisterFactory(CompressedArchiveFormat format, CompressedArchiveAccessImplementation implementation, CompressedArchiveAccessFactory factory) { if (format == CompressedArchiveFormat.None) { var message = string.Format(CultureInfo.CurrentCulture, Resources.Strings.CompressedArchiveAccess_InvalidCompressionFormatTypeErrorMessage_Format, format); throw new ArgumentOutOfRangeException("format", message); } if ((implementation == CompressedArchiveAccessImplementation.None) || (implementation == CompressedArchiveAccessImplementation.Any)) { var message = string.Format(CultureInfo.CurrentCulture, Resources.Strings.CompressedArchiveAccess_InvalidCompressionImplementationTypeErrorMessage_Format, implementation, format); throw new ArgumentOutOfRangeException("implementation", message); } var registered = Factories.Value.TryAdd(new CompressedArchiveIdentifier(format, implementation), factory); return(registered); }
/// <summary> /// Associates a file extension with a previously registered <see cref="CompressedArchiveFormat"/>. /// </summary> /// <param name="format">The compressed archive format with which to associate a file extension.</param> /// <param name="fileExtension">The file extension to associate with <paramref name="format"/>.</param> /// <param name="makeDefault">If <c>true</c>, treat <paramref name="fileExtension"/> as the default, meaning the first in the enumerable of values returned from <see cref="FileExtensions(CompressedArchiveFormat)"/>.</param> /// <returns><c>true</c> if the file extension was added to those associated with <paramref name="format"/>, <c>false</c> otherwise.</returns> /// <remarks>Note that if a particular file extension is not already the default, you can make it so by calling this method and setting <paramref name="makeDefault"/> /// to <c>true</c>. In this usage, the function will always return <c>false</c> if <paramref name="fileExtension"/> is already associated with <paramref name="format"/>. /// Note also that file extensions are not case sensitive.</remarks> /// <exception cref="System.ArgumentOutOfRangeException">Thrown if <paramref name="format"/> is <see cref="CompressedArchiveFormat.None"/>.</exception> /// <exception cref="System.ArgumentException">Thrown if <paramref name="fileExtension"/> is null, empty, whitespace, contains invalid characters, /// does not begin with a period, or contains multiple periods. This exception is also thrown if <paramref name="format"/> has not already /// been registered as an available format, either as a format automatically included in the implementation, or registered via /// <see cref="RegisterCompressedArchiveFormat(CompressedArchiveFormat, IEnumerable{string}, IEnumerable{CompressedArchiveAccessImplementation})"/>. /// This exception is also thrown if <paramref name="fileExtension"/> is already in use by a previously registered <paramref name="format"/>.</exception> public static bool AddFileExtension(this CompressedArchiveFormat format, string fileExtension, bool makeDefault) { if (format == CompressedArchiveFormat.None) { throw new ArgumentOutOfRangeException("format"); } if (string.IsNullOrWhiteSpace(fileExtension) || (fileExtension.First() != '.') || Path.GetInvalidFileNameChars().Intersect(fileExtension).Any()) { throw new ArgumentException(Resources.Strings.CompressedArchiveFormat_InvalidFileExtensionError, "fileExtension"); } if (fileExtension.Count(c => c == '.') > 1) { throw new ArgumentException(Resources.Strings.CompressedArchiveFormat_CompountFileExtensionsNotSupportedError, "fileExtension"); } lock (Lock) { List <string> existingFileExtensionsForFormat; var formatAlreadyRegistered = CompressedArchiveFormatFileExtensions.Value.TryGetValue(format, out existingFileExtensionsForFormat); var formatAlreadyUsingExtension = CompressedArchiveFormatFileExtensions.Value.FirstOrDefault(e => e.Value.Contains(fileExtension, StringComparer.OrdinalIgnoreCase)); bool?added = null; if (formatAlreadyRegistered) { if ((formatAlreadyUsingExtension.Key == CompressedArchiveFormat.None) || (formatAlreadyUsingExtension.Key == format)) { added = AddOrUpdateCompressedArchiveFormatData(fileExtension, makeDefault, existingFileExtensionsForFormat, (f, e) => ((List <string>)e).FindIndex(0, x => StringComparer.OrdinalIgnoreCase.Compare(x, f) == 0)); } } else { var message = string.Format(CultureInfo.CurrentCulture, Resources.Strings.CompressedArchiveFormat_FormatIsNotRegisteredError_Format, format); throw new ArgumentException(message, "format"); } if (!added.HasValue) { var message = string.Format(CultureInfo.CurrentCulture, Resources.Strings.CompressedArchiveFormat_FileExtensionAlreadyInUseError_Format, fileExtension, formatAlreadyUsingExtension.Key); throw new ArgumentException(message, "fileExtension"); } return(added.Value); } }
public static TestCompressedArchiveAccess Create( Stream stream, CompressedArchiveAccessMode mode, CompressedArchiveFormat format, CompressedArchiveAccessImplementation implementation, string firstEntryName = null, bool isArchive = true, bool isCompressed = true) { var testArchiveAccess = new TestCompressedArchiveAccess() { Mode = mode, _format = format, Implementation = implementation }; testArchiveAccess._isArchive = isArchive; testArchiveAccess._isCompressed = isCompressed; if (!string.IsNullOrWhiteSpace(firstEntryName)) { testArchiveAccess.CreateAndAddEntry(firstEntryName); } return(testArchiveAccess); }
/// <summary> /// Checks whether the given <see cref="CompressedArchiveFormat"/> is currently supported. /// </summary> /// <param name="format">The compressed archive format to check availability for.</param> /// <returns><c>true</c> if the archive format is supported, <c>false</c> otherwise.</returns> public static bool IsCompressedArchiveFormatSupported(this CompressedArchiveFormat format) { return(AvailableFormats.Contains(format)); }
/// <summary> /// Gets the preferred implementation of the given compressed archive format. /// </summary> /// <param name="format">The format whose preferred implementation is desired.</param> /// <returns>The preferred implementation, or <see cref="CompressedArchiveAccessImplementation.None"/> if none is available.</returns> public static CompressedArchiveAccessImplementation GetPreferredCompressedArchiveImplementation(this CompressedArchiveFormat format) { var preferredImplementation = format.GetAvailableCompressedArchiveImplementations().FirstOrDefault(); return(preferredImplementation); }
/// <summary> /// Gets the available implementations of the given compressed archive format. /// </summary> /// <param name="format">The compressed archive format whose available implementations are desired.</param> /// <returns>The available implementations. If unsupported, an empty enumerable is returned.</returns> public static IEnumerable <CompressedArchiveAccessImplementation> GetAvailableCompressedArchiveImplementations(this CompressedArchiveFormat format) { lock (Lock) { var implementations = Enumerable.Empty <CompressedArchiveAccessImplementation>(); IList <CompressedArchiveAccessImplementation> registeredImplementations; if (format.IsCompressedArchiveFormatSupported() && CompressedArchiveAccessImplementations.Value.TryGetValue(format, out registeredImplementations)) { implementations = registeredImplementations; } return(implementations); } }
/// <summary> /// Initializes a new instance of <see cref="CompressedArchiveIdentifier"/>. /// </summary> /// <param name="format">The compressed archive format to use in the identifier.</param> /// <param name="implementation">The compressed archive access implementation kind to use in the identifier.</param> public CompressedArchiveIdentifier(CompressedArchiveFormat format, CompressedArchiveAccessImplementation implementation) { _format = format; _implementation = implementation; }
public void CompressedArchiveFormat_FileExtensions_ReturnsExpectedExtensions(CompressedArchiveFormat format, IEnumerable <string> expectedExtensions) { var extensions = format.FileExtensions(); Assert.Equal(expectedExtensions, extensions, StringComparer.InvariantCultureIgnoreCase); }
public void CompressedArchiveFormat_IsCompressedArchiveFormatSupported_ReturnsCorrectValue(CompressedArchiveFormat format, bool expectedIsSupported) { Assert.Equal(expectedIsSupported, format.IsCompressedArchiveFormatSupported()); }
public void CompressedArchiveFormat_GetPreferredCompressedArchiveImplementation_ReturnsExpectedPreferredImplementation(CompressedArchiveFormat format, CompressedArchiveAccessImplementation expectedPreferredImplementation) { var preferredImplementation = format.GetPreferredCompressedArchiveImplementation(); Assert.Equal(expectedPreferredImplementation, preferredImplementation); }
public void CompressedArchiveFormat_GetAvailableCompressedArchiveImplementations_ReturnsExpectedImplementations(CompressedArchiveFormat format, IEnumerable <CompressedArchiveAccessImplementation> expectedImplementations) { var implementations = format.GetAvailableCompressedArchiveImplementations(); Assert.Equal(expectedImplementations, implementations); }