From b244318e3ad524231e36647037e22ace93700c80 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Fri, 6 Aug 2021 18:51:55 -0700 Subject: [PATCH] Add XML docs to Path --- src/LibHac/Fs/Common/Path.cs | 253 ++++++++++++++++++++++++++++++++++- 1 file changed, 250 insertions(+), 3 deletions(-) diff --git a/src/LibHac/Fs/Common/Path.cs b/src/LibHac/Fs/Common/Path.cs index b00ba58f..ad12394e 100644 --- a/src/LibHac/Fs/Common/Path.cs +++ b/src/LibHac/Fs/Common/Path.cs @@ -26,9 +26,25 @@ namespace LibHac.Fs public bool IsBackslashAllowed() => (_value & (1 << 4)) != 0; } + /// + /// Represents a file path stored as a UTF-8 string. + /// + /// + /// A has three parts to it:
+ /// 1. A that points to the current path string.
+ /// 2. A write buffer that can be allocated if operations need to be done on the path.
+ /// 3. An IsNormalized flag that tracks the path normalization status of the current path.
+ /// There are two different ways to initialize a . The "Initialize*" methods will + /// ensure a write buffer is allocated and copy the input path to it. will + /// directly use the input buffer without copying. If this method is used, the caller must ensure the path + /// is normalized before passing it to . + ///
Based on FS 12.0.3 (nnSdk 12.3.1)
[DebuggerDisplay("{" + nameof(ToString) + "(),nq}")] public ref struct Path { + /// + /// Used to store a path in a non-ref struct. + /// [DebuggerDisplay("{" + nameof(ToString) + "(),nq}")] public struct Stored : IDisposable { @@ -44,6 +60,14 @@ namespace LibHac.Fs } } + /// + /// Initializes this path with the data from a standard . + /// must be normalized. + /// + /// The used to initialize this one. + /// : The operation was successful.
+ /// : The IsNormalized flag of + /// is not .
public Result Initialize(in Path path) { if (!path._isNormalized) @@ -119,27 +143,50 @@ namespace LibHac.Fs } } + /// + /// Gets the current write buffer. + /// + /// The write buffer. internal Span GetWriteBuffer() { Assert.SdkRequires(_writeBuffer is not null); return _writeBuffer.AsSpan(); } + /// + /// Gets the current length of the write buffer. + /// + /// The write buffer length. internal readonly long GetWriteBufferLength() { return _writeBufferLength; } + /// + /// Calculates the length of the current string. + /// + /// The length of the current string> public readonly int GetLength() { return StringUtils.GetLength(GetString()); } + /// + /// Returns if + /// + /// public readonly bool IsEmpty() { return _string.At(0) == 0; } + /// + /// Calculates if the first "" characters of the + /// current path and are the same. + /// + /// The string to compare to this . + /// The maximum number of characters to compare. + /// if the strings are the same; otherwise . public readonly bool IsMatchHead(ReadOnlySpan value, int length) { return StringUtils.Compare(GetString(), value, length) == 0; @@ -165,6 +212,10 @@ namespace LibHac.Fs return StringUtils.Compare(left.GetString(), right) == 0; } + /// + /// Releases this 's write buffer and returns it to the caller. + /// + /// The write buffer if the had one; otherwise . public byte[] ReleaseBuffer() { Assert.SdkRequires(_writeBuffer is not null); @@ -175,6 +226,9 @@ namespace LibHac.Fs return Shared.Move(ref _writeBuffer); } + /// + /// Releases any current write buffer and sets this to an empty string. + /// private void ClearBuffer() { byte[] oldBuffer = Shared.Move(ref _writeBuffer); @@ -186,6 +240,12 @@ namespace LibHac.Fs _string = EmptyPath; } + /// + /// Releases any current write buffer and sets the provided buffer as the new write buffer. + /// + /// The new write buffer. + /// The length of the write buffer. + /// Must be a multiple of . private void SetModifiableBuffer(byte[] buffer, int length) { Assert.SdkRequiresNotNull(buffer); @@ -202,6 +262,10 @@ namespace LibHac.Fs _string = buffer; } + /// + /// Releases any current write buffer and sets as this 's string. + /// + /// The buffer containing the new path. private void SetReadOnlyBuffer(ReadOnlySpan buffer) { _string = buffer; @@ -214,6 +278,11 @@ namespace LibHac.Fs _writeBufferLength = 0; } + /// + /// Ensures the write buffer is the specified or larger. + /// + /// The minimum desired length. + /// : The operation was successful. private Result Preallocate(int length) { if (_writeBufferLength > length) @@ -226,6 +295,14 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Releases any current write buffer and sets as this 's string.
+ /// The path contained by must be normalized. + ///
+ /// It is up to the caller to ensure the path contained by is normalized. + /// This function will always set the IsNormalized flag to . + /// The buffer containing the new path. + /// : The operation was successful. public Result SetShallowBuffer(ReadOnlySpan buffer) { Assert.SdkRequires(_writeBufferLength == 0); @@ -235,6 +312,12 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Gets the buffer containing the current path. + /// + /// This 's IsNormalized flag should be + /// before calling this function. + /// The buffer containing the current path. public readonly ReadOnlySpan GetString() { Assert.SdkAssert(_isNormalized); @@ -242,6 +325,16 @@ namespace LibHac.Fs return _string; } + /// + /// Initializes this with the data from another Path.
+ /// must be normalized. + ///
+ /// This 's IsNormalized flag will be set to + /// the value of 's flag. + /// The used to initialize this one. + /// : The operation was successful.
+ /// : The IsNormalized flag of + /// is not .
public Result Initialize(in Path other) { if (!other._isNormalized) @@ -261,6 +354,14 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Initializes this with the data from a path. + /// + /// Ensures we have a large enough write buffer and copies the path to it. + /// This function always sets the IsNormalized flag to + /// because paths are always normalized upon initialization. + /// The path used to initialize this . + /// : The operation was successful. public Result Initialize(in Stored other) { int otherLength = other.GetLength(); @@ -277,6 +378,15 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Initializes this using the path in the provided buffer. + /// + /// Ensures the write buffer is large enough to hold + /// and copies to the write buffer.
+ /// This function does not modify the IsNormalized flag.
+ /// The buffer containing the path to use. + /// The length of the provided path. + /// : The operation was successful. private Result InitializeImpl(ReadOnlySpan path, int length) { if (length == 0 || path.At(0) == NullTerminator) @@ -296,6 +406,14 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Initializes this using the path in the provided buffer. + /// + /// Ensures the write buffer is large enough to hold + /// and copies to the write buffer.
+ /// This function will always set the IsNormalized flag to .
+ /// The buffer containing the path to use. + /// : The operation was successful. public Result Initialize(ReadOnlySpan path) { Result rc = InitializeImpl(path, StringUtils.GetLength(path)); @@ -305,6 +423,19 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Initializes this using the path in the provided buffer and + /// normalizes it if the path is a relative path or a Windows path. + /// + /// This function normalizes relative paths and Windows paths but does not normalize any other paths, + /// although all paths are checked for invalid characters and if the path is in a valid format.
+ /// The IsNormalized flag will always be set to even if the incoming path + /// is not normalized. This can lead to a situation where the path is not normalized yet the + /// IsNormalized flag is still .
+ /// The buffer containing the path to use. + /// : The operation was successful.
+ /// : The path contains an invalid character.
+ /// : The path is not in a valid format.
public Result InitializeWithNormalization(ReadOnlySpan path) { Result rc = Initialize(path); @@ -340,6 +471,15 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Initializes this using the path in the provided buffer. + /// + /// Ensures the write buffer is large enough to hold + /// and copies to the write buffer.
+ /// This function will always set the IsNormalized flag to .
+ /// The buffer containing the path to use. + /// The length of the provided path. + /// : The operation was successful. public Result Initialize(ReadOnlySpan path, int length) { Result rc = InitializeImpl(path, length); @@ -349,6 +489,20 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Initializes this using the path in the provided buffer and + /// normalizes it if the path is a relative path or a Windows path. + /// + /// This function normalizes relative paths and Windows paths but does not normalize any other paths, + /// although all paths are checked for invalid characters and if the path is in a valid format.
+ /// The IsNormalized flag will always be set to even if the incoming path + /// is not normalized. This can lead to a situation where the path is not normalized yet the + /// IsNormalized flag is still .
+ /// The buffer containing the path to use. + /// The length of the provided path. + /// : The operation was successful.
+ /// : The path contains an invalid character.
+ /// : The path is not in a valid format.
public Result InitializeWithNormalization(ReadOnlySpan path, int length) { Result rc = Initialize(path, length); @@ -384,6 +538,14 @@ namespace LibHac.Fs return Result.Success; } + + /// + /// Initializes this using the path in the provided buffer and + /// replaces any backslashes in the path with forward slashes. + /// + /// This function will always set the IsNormalized flag to . + /// The buffer containing the path to use. + /// : The operation was successful. public Result InitializeWithReplaceBackslash(ReadOnlySpan path) { Result rc = InitializeImpl(path, StringUtils.GetLength(path)); @@ -399,6 +561,13 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Initializes this using the path in the provided buffer. If the path begins with two + /// forward slashes (//), those two forward slashes will be replaced with two backslashes (\\). + /// + /// This function will always set the IsNormalized flag to . + /// The buffer containing the path to use. + /// : The operation was successful. public Result InitializeWithReplaceForwardSlashes(ReadOnlySpan path) { Result rc = InitializeImpl(path, StringUtils.GetLength(path)); @@ -418,6 +587,18 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Initializes this using the path in the provided buffer + /// and makes various UNC path-related replacements. + /// + /// The following replacements are made:
+ /// :/// located anywhere in the path is replaced with :/\\
+ /// @Host:// located at the beginning of the path is replaced with @Host:\\
+ /// // located at the beginning of the path is replaced with \\ + /// This function does not modify the IsNormalized flag. + ///
+ /// The buffer containing the path to use. + /// : The operation was successful. public Result InitializeWithReplaceUnc(ReadOnlySpan path) { Result rc = InitializeImpl(path, StringUtils.GetLength(path)); @@ -455,6 +636,11 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Initializes the as an empty string. + /// + /// This function will always set the IsNormalized flag to . + /// : The operation was successful. public Result InitializeAsEmpty() { ClearBuffer(); @@ -463,6 +649,15 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Updates this by prepending to the current path. + /// + /// This function does not modify the IsNormalized flag. + /// If is not normalized, this can lead to a situation where the resulting + /// path is not normalized yet the IsNormalized flag is still . + /// The buffer containing the path to insert. + /// : The operation was successful.
+ /// : The path provided in is a Windows path.
public Result InsertParent(ReadOnlySpan parent) { if (parent.Length == 0 || parent[0] == NullTerminator) @@ -566,11 +761,28 @@ namespace LibHac.Fs } } + /// + /// Updates this by prepending to the current path. + /// + /// This function does not modify the IsNormalized flag. + /// If is not normalized, this can lead to a situation where the resulting + /// path is not normalized yet the IsNormalized flag is still . + /// The to insert. + /// : The operation was successful.
+ /// : The path provided in is a Windows path.
public Result InsertParent(in Path parent) { return InsertParent(parent.GetString()); } + /// + /// Updates this by appending to the current path. + /// + /// This function does not modify the IsNormalized flag. + /// If is not normalized, this can lead to a situation where the resulting + /// path is not normalized yet the IsNormalized flag is still . + /// The buffer containing the child path to append to the current path. + /// : The operation was successful. public Result AppendChild(ReadOnlySpan child) { ReadOnlySpan trimmedChild = child; @@ -643,11 +855,30 @@ namespace LibHac.Fs } } + /// + /// Updates this by appending to the current path. + /// + /// This function does not modify the IsNormalized flag. + /// If is not normalized, this can lead to a situation where the resulting + /// path is not normalized yet the IsNormalized flag is still . + /// The child to append to the current path. + /// : The operation was successful. public Result AppendChild(in Path child) { return AppendChild(child.GetString()); } + /// + /// Combines 2 s into a single path. + /// + /// If is empty, this 's IsNormalized flag will + /// be set to the value of 's flag. + /// Otherwise the flag will be set to the value of 's flag. + /// The first path to combine. + /// The second path to combine. + /// : The operation was successful.
+ /// : The IsNormalized flag of either + /// or is not .
public Result Combine(in Path path1, in Path path2) { int path1Length = path1.GetLength(); @@ -656,23 +887,30 @@ namespace LibHac.Fs Result rc = Preallocate(path1Length + SeparatorLength + path2Length + NullTerminatorLength); if (rc.IsFailure()) return rc; - rc = Initialize(path1); + rc = Initialize(in path1); if (rc.IsFailure()) return rc; if (IsEmpty()) { - rc = Initialize(path2); + rc = Initialize(in path2); if (rc.IsFailure()) return rc; } else { - rc = AppendChild(path2); + rc = AppendChild(in path2); if (rc.IsFailure()) return rc; } return Result.Success; } + /// + /// Removes the last entry from this . + /// + /// This function does not modify the IsNormalized flag. + /// : The operation was successful.
+ /// : The path before calling this function was + /// one of ".", "..", "/" or "\".
public Result RemoveChild() { // Make sure the Path has a buffer that we can write to. @@ -742,6 +980,15 @@ namespace LibHac.Fs return Result.Success; } + /// + /// Normalizes the current path according to the provided . + /// + /// If this 's IsNormalized flag is set, this function does nothing. + /// The IsNormalized flag will be set if this function returns successfully. + /// Flags that specify what types of paths are allowed. + /// : The operation was successful.
+ /// : The path contains an invalid character.
+ /// : The path is in an invalid format for the specified .
public Result Normalize(PathFlags flags) { if (_isNormalized)