2020-12-21 11:50:46 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
using System ;
using System.Collections.Generic ;
2021-04-27 22:41:48 -04:00
using System.Diagnostics.CodeAnalysis ;
2020-12-21 11:50:46 -04:00
using System.IO ;
using System.Linq ;
using System.Text ;
2021-04-27 22:41:48 -04:00
using System.Threading ;
2020-12-21 11:50:46 -04:00
using System.Threading.Tasks ;
2020-12-21 23:07:37 -04:00
namespace EpicGames.Core
2020-12-21 11:50:46 -04:00
{
/// <summary>
/// Representation of an absolute file path. Allows fast hashing and comparisons.
/// </summary>
[Serializable]
2022-02-15 10:02:06 -05:00
public class FileReference : FileSystemReference , IEquatable < FileReference > , IComparable < FileReference >
2020-12-21 11:50:46 -04:00
{
/// <summary>
/// Dummy enum to allow invoking the constructor which takes a sanitized full path
/// </summary>
public enum Sanitize
{
2022-06-22 13:23:01 -04:00
/// <summary>
/// Dummy value
/// </summary>
2020-12-21 11:50:46 -04:00
None
}
/// <summary>
/// Default constructor.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="inPath">Path to this file</param>
public FileReference ( string inPath )
: base ( Path . GetFullPath ( inPath ) )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
if ( FullName [ ^ 1 ] = = '\\' | | FullName [ ^ 1 ] = = '/' )
2020-12-21 11:50:46 -04:00
{
throw new ArgumentException ( "File names may not be terminated by a path separator character" ) ;
}
}
/// <summary>
/// Construct a FileReference from a FileInfo object.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="inInfo">Path to this file</param>
public FileReference ( FileInfo inInfo )
: base ( inInfo . FullName )
2020-12-21 11:50:46 -04:00
{
}
/// <summary>
/// Default constructor.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="fullName">The full sanitized path</param>
2022-06-22 13:23:01 -04:00
/// <param name="sanitize">Sanitize argument. Ignored.</param>
public FileReference ( string fullName , Sanitize sanitize )
2022-03-24 16:35:00 -04:00
: base ( fullName )
2020-12-21 11:50:46 -04:00
{
}
/// <summary>
/// Create a FileReference from a string. If the string is null, returns a null FileReference.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="fileName">FileName for the string</param>
2020-12-21 11:50:46 -04:00
/// <returns>Returns a FileReference representing the given string, or null.</returns>
2022-03-24 16:35:00 -04:00
[return: NotNullIfNotNull("fileName")]
public static FileReference ? FromString ( string? fileName )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
if ( String . IsNullOrEmpty ( fileName ) )
2020-12-21 11:50:46 -04:00
{
return null ;
}
else
{
2022-03-24 16:35:00 -04:00
return new FileReference ( fileName ) ;
2020-12-21 11:50:46 -04:00
}
}
/// <summary>
/// Gets the file name without path information
/// </summary>
/// <returns>A string containing the file name</returns>
public string GetFileName ( )
{
return Path . GetFileName ( FullName ) ;
}
/// <summary>
/// Gets the file name without path information or an extension
/// </summary>
/// <returns>A string containing the file name without an extension</returns>
public string GetFileNameWithoutExtension ( )
{
return Path . GetFileNameWithoutExtension ( FullName ) ;
}
/// <summary>
/// Gets the file name without path or any extensions
/// </summary>
/// <returns>A string containing the file name without an extension</returns>
public string GetFileNameWithoutAnyExtensions ( )
{
2022-03-24 16:35:00 -04:00
int startIdx = FullName . LastIndexOf ( Path . DirectorySeparatorChar ) + 1 ;
2020-12-21 11:50:46 -04:00
2022-03-24 16:35:00 -04:00
int endIdx = FullName . IndexOf ( '.' , startIdx ) ;
if ( endIdx < startIdx )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return FullName . Substring ( startIdx ) ;
2020-12-21 11:50:46 -04:00
}
else
{
2022-03-24 16:35:00 -04:00
return FullName . Substring ( startIdx , endIdx - startIdx ) ;
2020-12-21 11:50:46 -04:00
}
}
/// <summary>
/// Gets the extension for this filename
/// </summary>
/// <returns>A string containing the extension of this filename</returns>
public string GetExtension ( )
{
return Path . GetExtension ( FullName ) ;
}
/// <summary>
/// Change the file's extension to something else
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="extension">The new extension</param>
2020-12-21 11:50:46 -04:00
/// <returns>A FileReference with the same path and name, but with the new extension</returns>
2022-03-24 16:35:00 -04:00
public FileReference ChangeExtension ( string? extension )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
string newFullName = Path . ChangeExtension ( FullName , extension ) ;
return new FileReference ( newFullName , Sanitize . None ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Gets the directory containing this file
/// </summary>
/// <returns>A new directory object representing the directory containing this object</returns>
public DirectoryReference Directory
{
get
{
2022-03-24 16:35:00 -04:00
int parentLength = FullName . LastIndexOf ( Path . DirectorySeparatorChar ) ;
2020-12-21 11:50:46 -04:00
2022-03-24 16:35:00 -04:00
if ( parentLength = = 2 & & FullName [ 1 ] = = ':' )
2020-12-21 11:50:46 -04:00
{
// windows root detected (C:)
2022-03-24 16:35:00 -04:00
parentLength + + ;
2020-12-21 11:50:46 -04:00
}
2022-03-24 16:35:00 -04:00
if ( parentLength = = 0 & & FullName [ 0 ] = = Path . DirectorySeparatorChar )
2020-12-21 11:50:46 -04:00
{
// nix style root (/) detected
2022-03-24 16:35:00 -04:00
parentLength = 1 ;
2020-12-21 11:50:46 -04:00
}
2022-03-24 16:35:00 -04:00
return new DirectoryReference ( FullName . Substring ( 0 , parentLength ) , DirectoryReference . Sanitize . None ) ;
2020-12-21 11:50:46 -04:00
}
}
/// <summary>
/// Combine several fragments with a base directory, to form a new filename
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="baseDirectory">The base directory</param>
/// <param name="fragments">Fragments to combine with the base directory</param>
2020-12-21 11:50:46 -04:00
/// <returns>The new file name</returns>
2022-03-24 16:35:00 -04:00
public static FileReference Combine ( DirectoryReference baseDirectory , params string [ ] fragments )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
string fullName = FileSystemReference . CombineStrings ( baseDirectory , fragments ) ;
return new FileReference ( fullName , Sanitize . None ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Append a string to the end of a filename
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="a">The base file reference</param>
/// <param name="b">Suffix to be appended</param>
2020-12-21 11:50:46 -04:00
/// <returns>The new file reference</returns>
2022-03-24 16:35:00 -04:00
public static FileReference operator + ( FileReference a , string b )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return new FileReference ( a . FullName + b , Sanitize . None ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Compares two filesystem object names for equality. Uses the canonical name representation, not the display name representation.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="a">First object to compare.</param>
/// <param name="b">Second object to compare.</param>
2020-12-21 11:50:46 -04:00
/// <returns>True if the names represent the same object, false otherwise</returns>
2022-03-24 16:35:00 -04:00
public static bool operator = = ( FileReference ? a , FileReference ? b )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
if ( a is null )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return b is null ;
}
else if ( b is null )
{
return false ;
2020-12-21 11:50:46 -04:00
}
else
{
2022-03-24 16:35:00 -04:00
return a . FullName . Equals ( b . FullName , Comparison ) ;
2020-12-21 11:50:46 -04:00
}
}
/// <summary>
/// Compares two filesystem object names for inequality. Uses the canonical name representation, not the display name representation.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="a">First object to compare.</param>
/// <param name="b">Second object to compare.</param>
2020-12-21 11:50:46 -04:00
/// <returns>False if the names represent the same object, true otherwise</returns>
2022-03-24 16:35:00 -04:00
public static bool operator ! = ( FileReference ? a , FileReference ? b )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return ! ( a = = b ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Compares against another object for equality.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="obj">other instance to compare.</param>
2020-12-21 11:50:46 -04:00
/// <returns>True if the names represent the same object, false otherwise</returns>
2022-03-24 16:35:00 -04:00
public override bool Equals ( object? obj ) = > obj is FileReference file & & file = = this ;
2020-12-21 11:50:46 -04:00
/// <summary>
/// Compares against another object for equality.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="obj">other instance to compare.</param>
2020-12-21 11:50:46 -04:00
/// <returns>True if the names represent the same object, false otherwise</returns>
2022-03-24 16:35:00 -04:00
public bool Equals ( FileReference ? obj )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return obj = = this ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Returns a hash code for this object
/// </summary>
/// <returns></returns>
public override int GetHashCode ( )
{
return Comparer . GetHashCode ( FullName ) ;
}
2022-02-15 10:02:06 -05:00
/// <inheritdoc/>
2022-03-24 16:35:00 -04:00
public int CompareTo ( FileReference ? other ) = > Comparer . Compare ( FullName , other ? . FullName ) ;
2022-02-15 10:02:06 -05:00
2020-12-21 11:50:46 -04:00
/// <summary>
/// Helper function to create a remote file reference. Unlike normal FileReference objects, these aren't converted to a full path in the local filesystem, but are
/// left as they are passed in.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="absolutePath">The absolute path in the remote file system</param>
2020-12-21 11:50:46 -04:00
/// <returns>New file reference</returns>
2022-03-24 16:35:00 -04:00
public static FileReference MakeRemote ( string absolutePath )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return new FileReference ( absolutePath , Sanitize . None ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Makes a file location writeable;
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
public static void MakeWriteable ( FileReference location )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
if ( Exists ( location ) )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
FileAttributes attributes = GetAttributes ( location ) ;
if ( ( attributes & FileAttributes . ReadOnly ) ! = 0 )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
SetAttributes ( location , attributes & ~ FileAttributes . ReadOnly ) ;
2020-12-21 11:50:46 -04:00
}
}
}
/// <summary>
/// Finds the correct case to match the location of this file on disk. Uses the given case for parts of the path that do not exist.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">The path to find the correct case for</param>
2020-12-21 11:50:46 -04:00
/// <returns>Location of the file with the correct case</returns>
2022-03-24 16:35:00 -04:00
public static FileReference FindCorrectCase ( FileReference location )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return new FileReference ( FileUtils . FindCorrectCase ( location . ToFileInfo ( ) ) ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Constructs a FileInfo object from this reference
/// </summary>
/// <returns>New FileInfo object</returns>
public FileInfo ToFileInfo ( )
{
return new FileInfo ( FullName ) ;
}
#region System . IO . File methods
/// <summary>
/// Copies a file from one location to another
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="sourceLocation">Location of the source file</param>
/// <param name="targetLocation">Location of the target file</param>
public static void Copy ( FileReference sourceLocation , FileReference targetLocation )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . Copy ( sourceLocation . FullName , targetLocation . FullName ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Copies a file from one location to another
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="sourceLocation">Location of the source file</param>
/// <param name="targetLocation">Location of the target file</param>
2020-12-21 11:50:46 -04:00
/// <param name="bOverwrite">Whether to overwrite the file in the target location</param>
2022-03-24 16:35:00 -04:00
public static void Copy ( FileReference sourceLocation , FileReference targetLocation , bool bOverwrite )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . Copy ( sourceLocation . FullName , targetLocation . FullName , bOverwrite ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Deletes this file
/// </summary>
2022-03-24 16:35:00 -04:00
public static void Delete ( FileReference location )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . Delete ( location . FullName ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Determines whether the given filename exists
/// </summary>
/// <returns>True if it exists, false otherwise</returns>
2022-03-24 16:35:00 -04:00
public static bool Exists ( FileReference location )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return File . Exists ( location . FullName ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Gets the attributes for a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
2020-12-21 11:50:46 -04:00
/// <returns>Attributes for the file</returns>
2022-03-24 16:35:00 -04:00
public static FileAttributes GetAttributes ( FileReference location )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return File . GetAttributes ( location . FullName ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Gets the time that the file was last written to
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
2020-12-21 11:50:46 -04:00
/// <returns>Last write time, in local time</returns>
2022-03-24 16:35:00 -04:00
public static DateTime GetLastWriteTime ( FileReference location )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return File . GetLastWriteTime ( location . FullName ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Gets the time that the file was last written to
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
2020-12-21 11:50:46 -04:00
/// <returns>Last write time, in UTC time</returns>
2022-03-24 16:35:00 -04:00
public static DateTime GetLastWriteTimeUtc ( FileReference location )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return File . GetLastWriteTimeUtc ( location . FullName ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Moves a file from one location to another
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="sourceLocation">Location of the source file</param>
/// <param name="targetLocation">Location of the target file</param>
public static void Move ( FileReference sourceLocation , FileReference targetLocation )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . Move ( sourceLocation . FullName , targetLocation . FullName ) ;
2020-12-21 11:50:46 -04:00
}
2021-04-27 22:41:48 -04:00
/// <summary>
/// Moves a file from one location to another
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="sourceLocation">Location of the source file</param>
/// <param name="targetLocation">Location of the target file</param>
/// <param name="overwrite">Whether to overwrite the file in the target location</param>
public static void Move ( FileReference sourceLocation , FileReference targetLocation , bool overwrite )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
File . Move ( sourceLocation . FullName , targetLocation . FullName , overwrite ) ;
2021-04-27 22:41:48 -04:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
/// Opens a FileStream on the specified path with read/write access
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="mode">Mode to use when opening the file</param>
2020-12-21 11:50:46 -04:00
/// <returns>New filestream for the given file</returns>
2022-03-24 16:35:00 -04:00
public static FileStream Open ( FileReference location , FileMode mode )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return File . Open ( location . FullName , mode ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Opens a FileStream on the specified path
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="mode">Mode to use when opening the file</param>
/// <param name="access">Sharing mode for the new file</param>
2020-12-21 11:50:46 -04:00
/// <returns>New filestream for the given file</returns>
2022-03-24 16:35:00 -04:00
public static FileStream Open ( FileReference location , FileMode mode , FileAccess access )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return File . Open ( location . FullName , mode , access ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Opens a FileStream on the specified path
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="mode">Mode to use when opening the file</param>
/// <param name="access">Access mode for the new file</param>
/// <param name="share">Sharing mode for the open file</param>
2020-12-21 11:50:46 -04:00
/// <returns>New filestream for the given file</returns>
2022-03-24 16:35:00 -04:00
public static FileStream Open ( FileReference location , FileMode mode , FileAccess access , FileShare share )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return File . Open ( location . FullName , mode , access , share ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Reads the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
2020-12-21 11:50:46 -04:00
/// <returns>Byte array containing the contents of the file</returns>
2022-03-24 16:35:00 -04:00
public static byte [ ] ReadAllBytes ( FileReference location )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return File . ReadAllBytes ( location . FullName ) ;
2020-12-21 11:50:46 -04:00
}
2021-04-27 22:41:48 -04:00
/// <summary>
/// Reads the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
2022-06-22 13:23:01 -04:00
/// <param name="cancellationToken">Cancellation token for the operation</param>
2021-04-27 22:41:48 -04:00
/// <returns>Byte array containing the contents of the file</returns>
2022-03-24 16:35:00 -04:00
public static Task < byte [ ] > ReadAllBytesAsync ( FileReference location , CancellationToken cancellationToken = default )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return File . ReadAllBytesAsync ( location . FullName , cancellationToken ) ;
2021-04-27 22:41:48 -04:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
/// Reads the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
2020-12-21 11:50:46 -04:00
/// <returns>Contents of the file as a single string</returns>
2022-03-24 16:35:00 -04:00
public static string ReadAllText ( FileReference location )
2020-12-21 11:50:46 -04:00
{
2022-04-27 14:16:14 -04:00
using ( FileStream fs = new FileStream ( location . FullName , FileMode . Open , FileAccess . Read , FileShare . Read , 4 * 1024 , FileOptions . SequentialScan ) )
{
using ( StreamReader sr = new StreamReader ( fs , Encoding . UTF8 , true ) )
{
// Try to read the whole file into a buffer created by hand. This avoids a LOT of memory allocations which in turn reduces the
// GC stress on the system. Removing the StreamReader would be nice in the future.
long RawFileLength = fs . Length ;
char [ ] InitialBuffer = new char [ RawFileLength ] ;
int ReadLength = sr . Read ( InitialBuffer , 0 , ( int ) RawFileLength ) ;
if ( sr . EndOfStream )
{
return new String ( InitialBuffer , 0 , ReadLength ) ;
}
else
{
string Remaining = sr . ReadToEnd ( ) ;
return String . Concat ( new ReadOnlySpan < char > ( InitialBuffer , 0 , ReadLength ) , Remaining ) ;
}
}
}
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Reads the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="encoding">Encoding of the file</param>
2020-12-21 11:50:46 -04:00
/// <returns>Contents of the file as a single string</returns>
2022-03-24 16:35:00 -04:00
public static string ReadAllText ( FileReference location , Encoding encoding )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return File . ReadAllText ( location . FullName , encoding ) ;
2020-12-21 11:50:46 -04:00
}
2021-04-27 22:41:48 -04:00
/// <summary>
/// Reads the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
2022-06-22 13:23:01 -04:00
/// <param name="cancellationToken">Cancellation token for the operation</param>
2021-04-27 22:41:48 -04:00
/// <returns>Contents of the file as a single string</returns>
2022-03-24 16:35:00 -04:00
public static Task < string > ReadAllTextAsync ( FileReference location , CancellationToken cancellationToken = default )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return File . ReadAllTextAsync ( location . FullName , cancellationToken ) ;
2021-04-27 22:41:48 -04:00
}
/// <summary>
/// Reads the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="encoding">Encoding of the file</param>
2022-06-22 13:23:01 -04:00
/// <param name="cancellationToken">Cancellation token for the operation</param>
2021-04-27 22:41:48 -04:00
/// <returns>Contents of the file as a single string</returns>
2022-03-24 16:35:00 -04:00
public static Task < string > ReadAllTextAsync ( FileReference location , Encoding encoding , CancellationToken cancellationToken = default )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return File . ReadAllTextAsync ( location . FullName , encoding , cancellationToken ) ;
2021-04-27 22:41:48 -04:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
/// Reads the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
2020-12-21 11:50:46 -04:00
/// <returns>String array containing the contents of the file</returns>
2022-03-24 16:35:00 -04:00
public static string [ ] ReadAllLines ( FileReference location )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return File . ReadAllLines ( location . FullName ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Reads the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
2020-12-21 11:50:46 -04:00
/// <returns>String array containing the contents of the file</returns>
2022-03-24 16:35:00 -04:00
public static string [ ] ReadAllLines ( FileReference location , Encoding encoding )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return File . ReadAllLines ( location . FullName , encoding ) ;
2020-12-21 11:50:46 -04:00
}
2021-04-27 22:41:48 -04:00
/// <summary>
/// Reads the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
2022-06-22 13:23:01 -04:00
/// <param name="cancellationToken">Cancellation token for the operation</param>
2021-04-27 22:41:48 -04:00
/// <returns>String array containing the contents of the file</returns>
2022-03-24 16:35:00 -04:00
public static Task < string [ ] > ReadAllLinesAsync ( FileReference location , CancellationToken cancellationToken = default )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return File . ReadAllLinesAsync ( location . FullName , cancellationToken ) ;
2021-04-27 22:41:48 -04:00
}
/// <summary>
/// Reads the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
2022-06-22 13:23:01 -04:00
/// <param name="cancellationToken">Cancellation token for the operation</param>
2021-04-27 22:41:48 -04:00
/// <returns>String array containing the contents of the file</returns>
2022-03-24 16:35:00 -04:00
public static Task < string [ ] > ReadAllLinesAsync ( FileReference location , Encoding encoding , CancellationToken cancellationToken = default )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return File . ReadAllLinesAsync ( location . FullName , encoding , cancellationToken ) ;
2021-04-27 22:41:48 -04:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
/// Sets the attributes for a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="attributes">New attributes for the file</param>
public static void SetAttributes ( FileReference location , FileAttributes attributes )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . SetAttributes ( location . FullName , attributes ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Sets the time that the file was last written to
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="lastWriteTime">Last write time, in local time</param>
public static void SetLastWriteTime ( FileReference location , DateTime lastWriteTime )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . SetLastWriteTime ( location . FullName , lastWriteTime ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Sets the time that the file was last written to
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="lastWriteTimeUtc">Last write time, in UTC time</param>
public static void SetLastWriteTimeUtc ( FileReference location , DateTime lastWriteTimeUtc )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . SetLastWriteTimeUtc ( location . FullName , lastWriteTimeUtc ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Sets the time that the file was last accessed.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file.</param>
/// <param name="lastWriteTime">Last access time, in local time.</param>
public static void SetLastAccessTime ( FileReference location , DateTime lastWriteTime )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . SetLastWriteTime ( location . FullName , lastWriteTime ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Sets the time that the file was last accessed.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file.</param>
2022-06-22 13:23:01 -04:00
/// <param name="lastWriteTimeUtc">Last access time, in UTC time.</param>
2022-03-24 16:35:00 -04:00
public static void SetLastAccessTimeUtc ( FileReference location , DateTime lastWriteTimeUtc )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . SetLastWriteTimeUtc ( location . FullName , lastWriteTimeUtc ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
public static void WriteAllBytes ( FileReference location , byte [ ] contents )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . WriteAllBytes ( location . FullName , contents ) ;
2020-12-21 11:50:46 -04:00
}
2021-04-27 22:41:48 -04:00
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
2022-06-22 13:23:01 -04:00
/// <param name="cancellationToken">Cancellation token for the operation</param>
2022-03-24 16:35:00 -04:00
public static Task WriteAllBytesAsync ( FileReference location , byte [ ] contents , CancellationToken cancellationToken = default )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return File . WriteAllBytesAsync ( location . FullName , contents , cancellationToken ) ;
2021-04-27 22:41:48 -04:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
2021-11-07 23:43:01 -05:00
/// Writes the data to the given file, if it's different from what's there already.
/// Returns true if contents were written.
2020-12-21 11:50:46 -04:00
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
public static bool WriteAllBytesIfDifferent ( FileReference location , byte [ ] contents )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
if ( FileReference . Exists ( location ) )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
byte [ ] currentContents = FileReference . ReadAllBytes ( location ) ;
if ( contents . AsSpan ( ) . SequenceEqual ( currentContents ) )
2020-12-21 11:50:46 -04:00
{
2021-11-07 23:43:01 -05:00
return false ;
2020-12-21 11:50:46 -04:00
}
}
2022-03-24 16:35:00 -04:00
WriteAllBytes ( location , contents ) ;
2021-11-07 23:43:01 -05:00
return true ;
}
/// <summary>
/// Writes the string to the given file, if it's different from what's there already.
/// Returns true if contents were written.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
public static bool WriteAllTextIfDifferent ( FileReference location , string contents )
2021-11-07 23:43:01 -05:00
{
2022-03-24 16:35:00 -04:00
if ( FileReference . Exists ( location ) )
2021-11-07 23:43:01 -05:00
{
2022-03-24 16:35:00 -04:00
string currentContents = FileReference . ReadAllText ( location ) ;
if ( String . Equals ( contents , currentContents ) )
2021-11-07 23:43:01 -05:00
{
return false ;
}
}
2022-03-24 16:35:00 -04:00
WriteAllText ( location , contents ) ;
2021-11-07 23:43:01 -05:00
return true ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
public static void WriteAllLines ( FileReference location , IEnumerable < string > contents )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . WriteAllLines ( location . FullName , contents ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
public static void WriteAllLines ( FileReference location , IEnumerable < string > contents , Encoding encoding )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . WriteAllLines ( location . FullName , contents , encoding ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
public static void WriteAllLines ( FileReference location , string [ ] contents )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . WriteAllLines ( location . FullName , contents ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
public static void WriteAllLines ( FileReference location , string [ ] contents , Encoding encoding )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . WriteAllLines ( location . FullName , contents , encoding ) ;
2020-12-21 11:50:46 -04:00
}
2021-04-27 22:41:48 -04:00
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
2022-06-22 13:23:01 -04:00
/// <param name="cancellationToken">Cancellation token for the operation</param>
2022-03-24 16:35:00 -04:00
public static Task WriteAllLinesAsync ( FileReference location , IEnumerable < string > contents , CancellationToken cancellationToken = default )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return File . WriteAllLinesAsync ( location . FullName , contents , cancellationToken ) ;
2021-04-27 22:41:48 -04:00
}
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
2022-06-22 13:23:01 -04:00
/// <param name="cancellationToken">Cancellation token for the operation</param>
2022-03-24 16:35:00 -04:00
public static Task WriteAllLinesAsync ( FileReference location , IEnumerable < string > contents , Encoding encoding , CancellationToken cancellationToken = default )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return File . WriteAllLinesAsync ( location . FullName , contents , encoding , cancellationToken ) ;
2021-04-27 22:41:48 -04:00
}
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
2022-06-22 13:23:01 -04:00
/// <param name="cancellationToken">Cancellation token for the operation</param>
2022-03-24 16:35:00 -04:00
public static Task WriteAllLinesAsync ( FileReference location , string [ ] contents , CancellationToken cancellationToken = default )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return File . WriteAllLinesAsync ( location . FullName , contents , cancellationToken ) ;
2021-04-27 22:41:48 -04:00
}
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
2022-06-22 13:23:01 -04:00
/// <param name="cancellationToken">Cancellation token for the operation</param>
2022-03-24 16:35:00 -04:00
public static Task WriteAllLinesAsync ( FileReference location , string [ ] contents , Encoding encoding , CancellationToken cancellationToken = default )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return File . WriteAllLinesAsync ( location . FullName , contents , encoding , cancellationToken ) ;
2021-04-27 22:41:48 -04:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
public static void WriteAllText ( FileReference location , string contents )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . WriteAllText ( location . FullName , contents ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
public static void WriteAllText ( FileReference location , string contents , Encoding encoding )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . WriteAllText ( location . FullName , contents , encoding ) ;
2021-06-02 09:18:12 -04:00
}
/// <summary>
/// Writes the contents of a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
public static Task WriteAllTextAsync ( FileReference location , string contents )
2021-06-02 09:18:12 -04:00
{
2022-03-24 16:35:00 -04:00
return File . WriteAllTextAsync ( location . FullName , contents ) ;
}
/// <summary>
/// Writes the contents of a file
/// </summary>
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents of the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
public static Task WriteAllTextAsync ( FileReference location , string contents , Encoding encoding )
{
return File . WriteAllTextAsync ( location . FullName , contents , encoding ) ;
2021-06-02 09:18:12 -04:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
public static void AppendAllLines ( FileReference location , IEnumerable < string > contents )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . AppendAllLines ( location . FullName , contents ) ;
2020-12-21 11:50:46 -04:00
}
2021-12-10 15:36:47 -05:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
public static Task AppendAllLinesAsync ( FileReference location , IEnumerable < string > contents )
2021-12-10 15:36:47 -05:00
{
2022-03-24 16:35:00 -04:00
return File . AppendAllLinesAsync ( location . FullName , contents ) ;
2021-12-10 15:36:47 -05:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
public static void AppendAllLines ( FileReference location , IEnumerable < string > contents , Encoding encoding )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . AppendAllLines ( location . FullName , contents , encoding ) ;
2020-12-21 11:50:46 -04:00
}
2021-12-10 15:36:47 -05:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
public static Task AppendAllLinesAsync ( FileReference location , IEnumerable < string > contents , Encoding encoding )
2021-12-10 15:36:47 -05:00
{
2022-03-24 16:35:00 -04:00
return File . AppendAllLinesAsync ( location . FullName , contents , encoding ) ;
2021-12-10 15:36:47 -05:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
public static void AppendAllLines ( FileReference location , string [ ] contents )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . AppendAllLines ( location . FullName , contents ) ;
2020-12-21 11:50:46 -04:00
}
2021-12-10 15:36:47 -05:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
public static Task AppendAllLinesAsync ( FileReference location , string [ ] contents )
2021-12-10 15:36:47 -05:00
{
2022-03-24 16:35:00 -04:00
return File . AppendAllLinesAsync ( location . FullName , contents ) ;
2021-12-10 15:36:47 -05:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
public static void AppendAllLines ( FileReference location , string [ ] contents , Encoding encoding )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . AppendAllLines ( location . FullName , contents , encoding ) ;
2020-12-21 11:50:46 -04:00
}
2021-12-10 15:36:47 -05:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
public static Task AppendAllLinesAsync ( FileReference location , string [ ] contents , Encoding encoding )
2021-12-10 15:36:47 -05:00
{
2022-03-24 16:35:00 -04:00
return File . AppendAllLinesAsync ( location . FullName , contents , encoding ) ;
2021-12-10 15:36:47 -05:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
public static void AppendAllText ( FileReference location , string contents )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . AppendAllText ( location . FullName , contents ) ;
2020-12-21 11:50:46 -04:00
}
2021-12-10 15:36:47 -05:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
public static Task AppendAllTextAsync ( FileReference location , string contents )
2021-12-10 15:36:47 -05:00
{
2022-03-24 16:35:00 -04:00
return File . AppendAllTextAsync ( location . FullName , contents ) ;
2021-12-10 15:36:47 -05:00
}
2020-12-21 11:50:46 -04:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
public static void AppendAllText ( FileReference location , string contents , Encoding encoding )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
File . AppendAllText ( location . FullName , contents , encoding ) ;
2020-12-21 11:50:46 -04:00
}
2021-12-10 15:36:47 -05:00
/// <summary>
/// Appends the contents to a file
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="location">Location of the file</param>
/// <param name="contents">Contents to append to the file</param>
/// <param name="encoding">The encoding to use when parsing the file</param>
public static Task AppendAllTextAsync ( FileReference location , string contents , Encoding encoding )
2021-12-10 15:36:47 -05:00
{
2022-03-24 16:35:00 -04:00
return File . AppendAllTextAsync ( location . FullName , contents , encoding ) ;
2021-12-10 15:36:47 -05:00
}
2020-12-21 11:50:46 -04:00
#endregion
}
/// <summary>
/// Extension methods for FileReference functionality
/// </summary>
public static class FileReferenceExtensionMethods
{
/// <summary>
/// Manually serialize a file reference to a binary stream.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="writer">Binary writer to write to</param>
/// <param name="file">The file reference to write</param>
public static void Write ( this BinaryWriter writer , FileReference file )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
writer . Write ( ( file = = null ) ? String . Empty : file . FullName ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Serializes a file reference, using a lookup table to avoid serializing the same name more than once.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="writer">The writer to save this reference to</param>
/// <param name="file">A file reference to output; may be null</param>
/// <param name="fileToUniqueId">A lookup table that caches previous files that have been output, and maps them to unique id's.</param>
public static void Write ( this BinaryWriter writer , FileReference file , Dictionary < FileReference , int > fileToUniqueId )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
int uniqueId ;
if ( file = = null )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
writer . Write ( - 1 ) ;
2020-12-21 11:50:46 -04:00
}
2022-03-24 16:35:00 -04:00
else if ( fileToUniqueId . TryGetValue ( file , out uniqueId ) )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
writer . Write ( uniqueId ) ;
2020-12-21 11:50:46 -04:00
}
else
{
2022-03-24 16:35:00 -04:00
writer . Write ( fileToUniqueId . Count ) ;
writer . Write ( file ) ;
fileToUniqueId . Add ( file , fileToUniqueId . Count ) ;
2020-12-21 11:50:46 -04:00
}
}
/// <summary>
/// Manually deserialize a file reference from a binary stream.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="reader">Binary reader to read from</param>
2020-12-21 11:50:46 -04:00
/// <returns>New FileReference object</returns>
2022-03-24 16:35:00 -04:00
public static FileReference ReadFileReference ( this BinaryReader reader )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return BinaryArchiveReader . NotNull ( ReadFileReferenceOrNull ( reader ) ) ;
2021-04-27 22:41:48 -04:00
}
/// <summary>
/// Manually deserialize a file reference from a binary stream.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="reader">Binary reader to read from</param>
2021-04-27 22:41:48 -04:00
/// <returns>New FileReference object</returns>
2022-03-24 16:35:00 -04:00
public static FileReference ? ReadFileReferenceOrNull ( this BinaryReader reader )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
string fullName = reader . ReadString ( ) ;
return ( fullName . Length = = 0 ) ? null : new FileReference ( fullName , FileReference . Sanitize . None ) ;
2020-12-21 11:50:46 -04:00
}
/// <summary>
/// Deserializes a file reference, using a lookup table to avoid writing the same name more than once.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="reader">The source to read from</param>
/// <param name="uniqueFiles">List of previously read file references. The index into this array is used in place of subsequent ocurrences of the file.</param>
2020-12-21 11:50:46 -04:00
/// <returns>The file reference that was read</returns>
2022-03-24 16:35:00 -04:00
public static FileReference ReadFileReference ( this BinaryReader reader , List < FileReference > uniqueFiles )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return BinaryArchiveReader . NotNull ( ReadFileReferenceOrNull ( reader , uniqueFiles ) ) ;
2021-04-27 22:41:48 -04:00
}
/// <summary>
/// Deserializes a file reference, using a lookup table to avoid writing the same name more than once.
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="reader">The source to read from</param>
/// <param name="uniqueFiles">List of previously read file references. The index into this array is used in place of subsequent ocurrences of the file.</param>
2021-04-27 22:41:48 -04:00
/// <returns>The file reference that was read</returns>
2022-03-24 16:35:00 -04:00
public static FileReference ? ReadFileReferenceOrNull ( this BinaryReader reader , List < FileReference > uniqueFiles )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
int uniqueId = reader . ReadInt32 ( ) ;
if ( uniqueId = = - 1 )
2020-12-21 11:50:46 -04:00
{
return null ;
}
2022-03-24 16:35:00 -04:00
else if ( uniqueId < uniqueFiles . Count )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
return uniqueFiles [ uniqueId ] ;
2020-12-21 11:50:46 -04:00
}
else
{
2022-03-24 16:35:00 -04:00
FileReference result = reader . ReadFileReference ( ) ;
uniqueFiles . Add ( result ) ;
return result ;
2020-12-21 11:50:46 -04:00
}
}
/// <summary>
/// Writes a FileReference to a binary archive
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="writer">The writer to output data to</param>
/// <param name="file">The file reference to write</param>
public static void WriteFileReference ( this BinaryArchiveWriter writer , FileReference ? file )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
if ( file = = null )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
writer . WriteString ( null ) ;
2020-12-21 11:50:46 -04:00
}
else
{
2022-03-24 16:35:00 -04:00
writer . WriteString ( file . FullName ) ;
2020-12-21 11:50:46 -04:00
}
}
/// <summary>
/// Reads a FileReference from a binary archive
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="reader">Reader to serialize data from</param>
2020-12-21 11:50:46 -04:00
/// <returns>New file reference instance</returns>
2022-03-24 16:35:00 -04:00
public static FileReference ReadFileReference ( this BinaryArchiveReader reader )
2021-04-27 22:41:48 -04:00
{
2022-03-24 16:35:00 -04:00
return BinaryArchiveReader . NotNull ( ReadFileReferenceOrNull ( reader ) ) ;
2021-04-27 22:41:48 -04:00
}
/// <summary>
/// Reads a FileReference from a binary archive
/// </summary>
2022-03-24 16:35:00 -04:00
/// <param name="reader">Reader to serialize data from</param>
2021-04-27 22:41:48 -04:00
/// <returns>New file reference instance</returns>
2022-03-24 16:35:00 -04:00
public static FileReference ? ReadFileReferenceOrNull ( this BinaryArchiveReader reader )
2020-12-21 11:50:46 -04:00
{
2022-03-24 16:35:00 -04:00
string? fullName = reader . ReadString ( ) ;
if ( fullName = = null )
2020-12-21 11:50:46 -04:00
{
return null ;
}
else
{
2022-03-24 16:35:00 -04:00
return new FileReference ( fullName , FileReference . Sanitize . None ) ;
2020-12-21 11:50:46 -04:00
}
}
}
}