2020-07-15 09:41:59 -07:00
using System ;
using System.IO ;
using SabreTools.Library.Data ;
namespace SabreTools.Library.Tools
{
/// <summary>
/// Extensions to Path functionality
/// </summary>
public static class PathExtensions
{
/// <summary>
/// Get the extension from the path, if possible
/// </summary>
/// <param name="path">Path to get extension from</param>
/// <returns>Extension, if possible</returns>
public static string GetNormalizedExtension ( string path )
{
// Check null or empty first
if ( string . IsNullOrWhiteSpace ( path ) )
return null ;
// Get the extension from the path, if possible
string ext = Path . GetExtension ( path ) ? . ToLowerInvariant ( ) ;
// Check if the extension is null or empty
if ( string . IsNullOrWhiteSpace ( ext ) )
return null ;
// Make sure that extensions are valid
ext = ext . TrimStart ( '.' ) ;
return ext ;
}
/// <summary>
/// Get the proper filename (with subpath) from the file and parent combination
/// </summary>
/// <param name="path">Input combined path to use</param>
/// <param name="sanitize">True if path separators should be converted to '-', false otherwise</param>
/// <returns>Subpath for the file</returns>
2020-07-26 23:39:33 -07:00
public static string GetNormalizedFileName ( ParentablePath path , bool sanitize )
2020-07-15 09:41:59 -07:00
{
// Check that we have a combined path first
2020-07-26 23:39:33 -07:00
if ( string . IsNullOrWhiteSpace ( path . ParentPath ) )
2020-07-15 09:41:59 -07:00
{
2020-07-26 23:39:33 -07:00
string filename = Path . GetFileName ( path . CurrentPath ) ;
2020-07-15 09:41:59 -07:00
if ( sanitize )
2020-07-19 12:57:13 -07:00
filename = filename . Replace ( Path . DirectorySeparatorChar , '-' ) . Replace ( Path . AltDirectorySeparatorChar , '-' ) ;
2020-07-15 09:41:59 -07:00
return filename ;
}
// If the parts are the same, return the filename from the first part
2020-07-26 23:39:33 -07:00
if ( string . Equals ( path . CurrentPath , path . ParentPath , StringComparison . Ordinal ) )
2020-07-15 09:41:59 -07:00
{
2020-07-26 23:39:33 -07:00
string filename = Path . GetFileName ( path . CurrentPath ) ;
2020-07-15 09:41:59 -07:00
if ( sanitize )
2020-07-19 12:57:13 -07:00
filename = filename . Replace ( Path . DirectorySeparatorChar , '-' ) . Replace ( Path . AltDirectorySeparatorChar , '-' ) ;
2020-07-15 09:41:59 -07:00
return filename ;
}
2020-07-26 23:39:33 -07:00
// Otherwise, remove the path.ParentPath from the path.CurrentPath and return the remainder
2020-07-15 09:41:59 -07:00
else
{
2020-07-26 23:39:33 -07:00
string filename = path . CurrentPath . Remove ( 0 , path . ParentPath . Length + 1 ) ;
2020-07-15 09:41:59 -07:00
if ( sanitize )
2020-07-19 12:57:13 -07:00
filename = filename . Replace ( Path . DirectorySeparatorChar , '-' ) . Replace ( Path . AltDirectorySeparatorChar , '-' ) ;
2020-07-15 09:41:59 -07:00
return filename ;
}
}
/// <summary>
/// Get the proper output path for a given input file and output directory
/// </summary>
/// <param name="outDir">Output directory to use</param>
/// <param name="inputpath">Input path to create output for</param>
/// <param name="inplace">True if the output file should go to the same input folder, false otherwise</param>
/// <returns>Complete output path</returns>
2020-07-26 23:39:33 -07:00
public static string GetOutputPath ( string outDir , ParentablePath inputPath , bool inplace )
2020-07-15 09:41:59 -07:00
{
// First, we need to ensure the output directory
outDir = DirectoryExtensions . Ensure ( outDir ) ;
// Check if we have a split path or not
2020-07-26 23:39:33 -07:00
bool splitpath = ! string . IsNullOrWhiteSpace ( inputPath . ParentPath ) ;
2020-07-15 09:41:59 -07:00
// If we have a split path, we need to treat the input separately
if ( splitpath )
{
// If we have an inplace output, use the directory name from the input path
if ( inplace )
{
2020-07-26 23:39:33 -07:00
outDir = Path . GetDirectoryName ( inputPath . CurrentPath ) ;
2020-07-15 09:41:59 -07:00
}
// TODO: Should this be the default? Always create a subfolder if a folder is found?
// If we are processing a path that is coming from a directory and we are outputting to the current directory, we want to get the subfolder to write to
2020-07-26 23:39:33 -07:00
else if ( inputPath . CurrentPath . Length ! = inputPath . ParentPath . Length & & outDir = = Environment . CurrentDirectory )
2020-07-15 09:41:59 -07:00
{
2020-07-26 23:39:33 -07:00
outDir = Path . GetDirectoryName ( Path . Combine ( outDir , inputPath . CurrentPath . Remove ( 0 , Path . GetDirectoryName ( inputPath . ParentPath ) . Length + 1 ) ) ) ;
2020-07-15 09:41:59 -07:00
}
// If we are processing a path that is coming from a directory, we want to get the subfolder to write to
2020-07-26 23:39:33 -07:00
else if ( inputPath . CurrentPath . Length ! = inputPath . ParentPath . Length )
2020-07-15 09:41:59 -07:00
{
2020-07-26 23:39:33 -07:00
outDir = Path . GetDirectoryName ( Path . Combine ( outDir , inputPath . CurrentPath . Remove ( 0 , inputPath . ParentPath . Length + 1 ) ) ) ;
2020-07-15 09:41:59 -07:00
}
// If we are processing a single file from the root of a directory, we just use the output directory
else
{
// No-op
}
}
// Otherwise, assume the input path is just a filename
else
{
// If we have an inplace output, use the directory name from the input path
if ( inplace )
{
2020-07-26 23:39:33 -07:00
outDir = Path . GetDirectoryName ( inputPath . CurrentPath ) ;
2020-07-15 09:41:59 -07:00
}
// Otherwise, just use the supplied output directory
else
{
// No-op
}
}
// Finally, return the output directory
return outDir ;
}
/// <summary>
/// Get a proper romba sub path
/// </summary>
/// <param name="hash">SHA-1 hash to get the path for</param>
/// <returns>Subfolder path for the given hash</returns>
public static string GetRombaPath ( string hash )
{
// If the hash isn't the right size, then we return null
if ( hash . Length ! = Constants . SHA1Length ) // TODO: When updating to SHA-256, this needs to update to Constants.SHA256Length
return null ;
return Path . Combine ( hash . Substring ( 0 , 2 ) , hash . Substring ( 2 , 2 ) , hash . Substring ( 4 , 2 ) , hash . Substring ( 6 , 2 ) , hash + ".gz" ) ;
}
/// <summary>
/// Get if the given path has a valid DAT extension
/// </summary>
/// <param name="path">Path to check</param>
/// <returns>True if the extension is valid, false otherwise</returns>
public static bool HasValidArchiveExtension ( string path )
{
// Get the extension from the path, if possible
string ext = PathExtensions . GetNormalizedExtension ( path ) ;
// Check against the list of known archive extensions
switch ( ext )
{
case "7z" :
case "gz" :
case "lzma" :
case "rar" :
case "rev" :
case "r00" :
case "r01" :
case "tar" :
case "tgz" :
case "tlz" :
case "zip" :
case "zipx" :
return true ;
default :
return false ;
}
}
/// <summary>
/// Get if the given path has a valid DAT extension
/// </summary>
/// <param name="path">Path to check</param>
/// <returns>True if the extension is valid, false otherwise</returns>
public static bool HasValidDatExtension ( string path )
{
// Get the extension from the path, if possible
string ext = GetNormalizedExtension ( path ) ;
// Check against the list of known DAT extensions
switch ( ext )
{
case "csv" :
case "dat" :
case "json" :
case "md5" :
case "ripemd160" :
case "sfv" :
case "sha1" :
case "sha256" :
case "sha384" :
case "sha512" :
case "ssv" :
case "tsv" :
case "txt" :
case "xml" :
return true ;
default :
return false ;
}
}
}
}