예제 #1
0
 /// <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);
     }
 }
예제 #2
0
        /// <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);
        }
예제 #3
0
            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);
            }
예제 #4
0
        /// <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);
        }
예제 #5
0
        /// <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);
            }
        }
예제 #6
0
            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);
            }
예제 #7
0
 /// <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));
 }
예제 #8
0
        /// <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);
        }
예제 #9
0
 /// <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);
     }
 }
예제 #10
0
 /// <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;
 }
예제 #11
0
        public void CompressedArchiveFormat_FileExtensions_ReturnsExpectedExtensions(CompressedArchiveFormat format, IEnumerable <string> expectedExtensions)
        {
            var extensions = format.FileExtensions();

            Assert.Equal(expectedExtensions, extensions, StringComparer.InvariantCultureIgnoreCase);
        }
예제 #12
0
 public void CompressedArchiveFormat_IsCompressedArchiveFormatSupported_ReturnsCorrectValue(CompressedArchiveFormat format, bool expectedIsSupported)
 {
     Assert.Equal(expectedIsSupported, format.IsCompressedArchiveFormatSupported());
 }
예제 #13
0
        public void CompressedArchiveFormat_GetPreferredCompressedArchiveImplementation_ReturnsExpectedPreferredImplementation(CompressedArchiveFormat format, CompressedArchiveAccessImplementation expectedPreferredImplementation)
        {
            var preferredImplementation = format.GetPreferredCompressedArchiveImplementation();

            Assert.Equal(expectedPreferredImplementation, preferredImplementation);
        }
예제 #14
0
        public void CompressedArchiveFormat_GetAvailableCompressedArchiveImplementations_ReturnsExpectedImplementations(CompressedArchiveFormat format, IEnumerable <CompressedArchiveAccessImplementation> expectedImplementations)
        {
            var implementations = format.GetAvailableCompressedArchiveImplementations();

            Assert.Equal(expectedImplementations, implementations);
        }