mirror of
https://github.com/chylex/Brotli-Builder.git
synced 2024-11-24 22:42:50 +01:00
95 lines
4.0 KiB
C#
95 lines
4.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace BrotliCalc.Helpers{
|
|
static class Brotli{
|
|
public const string CompressedFileExtension = ".br";
|
|
public const char DirectorySeparator = '/';
|
|
|
|
public static FileOrdering FileOrder { get; set; } = FileOrdering.System;
|
|
|
|
public enum FileOrdering{
|
|
System, Quality
|
|
}
|
|
|
|
private static readonly Regex RegexCompressionIdentifier = new Regex(@"\.([^.]+)\.br$");
|
|
|
|
private static string GetUncompressedName(string path){
|
|
return Path.GetExtension(path) == CompressedFileExtension ? RegexCompressionIdentifier.Replace(path, "") : path;
|
|
}
|
|
|
|
private static bool IsUncompressed(string path){
|
|
return Path.GetExtension(path) != CompressedFileExtension;
|
|
}
|
|
|
|
private static string GetSortKey(BrotliFile.Compressed file){
|
|
return file.Identifier.PadLeft(2, '0');
|
|
}
|
|
|
|
public static IEnumerable<BrotliFileGroup> ListPath(string path){
|
|
path = Path.GetFullPath(path);
|
|
|
|
bool isFolder = File.GetAttributes(path).HasFlag(FileAttributes.Directory);
|
|
string rootPath = isFolder ? path : Path.GetDirectoryName(path) ?? path;
|
|
int rootLength = rootPath.Length;
|
|
|
|
string GetRelativePath(string file){
|
|
return file.Substring(rootLength).Replace(Path.DirectorySeparatorChar, DirectorySeparator).Replace(Path.AltDirectorySeparatorChar, DirectorySeparator).TrimStart(DirectorySeparator);
|
|
}
|
|
|
|
BrotliFileGroup ProcessGroup(IGrouping<string, string> group){
|
|
var uncompressed = group.FirstOrDefault(IsUncompressed);
|
|
var compressed = group.Except(new string[]{ uncompressed });
|
|
|
|
if (uncompressed == null){
|
|
throw new ArgumentException("Missing uncompressed file in group:\n" + string.Join(",\n", compressed), nameof(group));
|
|
}
|
|
|
|
return new BrotliFileGroup(
|
|
new BrotliFile.Uncompressed(uncompressed, GetRelativePath(uncompressed)),
|
|
compressed.Select(ConstructCompressed).OrderBy(GetSortKey).ToArray()
|
|
);
|
|
}
|
|
|
|
BrotliFile.Compressed ConstructCompressed(string file){
|
|
var match = RegexCompressionIdentifier.Match(file);
|
|
var identifier = match.Success ? match.Groups[1].Value : "?";
|
|
|
|
return new BrotliFile.Compressed(file, GetUncompressedName(GetRelativePath(file)), identifier);
|
|
}
|
|
|
|
IEnumerable<IGrouping<string, string>> groupings;
|
|
|
|
if (isFolder){
|
|
groupings = Directory.EnumerateFiles(rootPath, "*.*", SearchOption.AllDirectories).GroupBy(GetUncompressedName);
|
|
}
|
|
else{
|
|
var group = GetUncompressedName(path);
|
|
groupings = Directory.EnumerateFiles(rootPath, "*.*", SearchOption.TopDirectoryOnly).GroupBy(GetUncompressedName).Where(g => g.Key == group).Take(1);
|
|
}
|
|
|
|
return groupings.Select(ProcessGroup);
|
|
}
|
|
|
|
public static IEnumerable<(BrotliFileGroup, BrotliFile.Uncompressed)> SelectUncompressedFiles(this IEnumerable<BrotliFileGroup> me){
|
|
return me.Select(group => (group, group.Uncompressed));
|
|
}
|
|
|
|
public static IEnumerable<(BrotliFileGroup, BrotliFile.Compressed)> SelectCompressedFiles(this IEnumerable<BrotliFileGroup> me){
|
|
var files = me.SelectMany(group => group.Compressed.Select(file => (group, file)));
|
|
|
|
return FileOrder switch{
|
|
FileOrdering.Quality => files.OrderBy(item => {
|
|
var identifier = item.file.Identifier;
|
|
return int.TryParse(identifier, out int _) ? identifier.PadLeft(item.group.Compressed.Max(file => file.Identifier.Length), '0') : identifier;
|
|
}),
|
|
|
|
_ => files
|
|
};
|
|
}
|
|
}
|
|
}
|