Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
PathHelper.cs
Go to the documentation of this file.
2using System.Text;
3
4namespace System.IO;
5
6internal static class PathHelper
7{
8 internal static string Normalize(string path)
9 {
10 Span<char> initialBuffer = stackalloc char[260];
11 ValueStringBuilder builder = new ValueStringBuilder(initialBuffer);
12 GetFullPathName(path.AsSpan(), ref builder);
13 string result = ((builder.AsSpan().IndexOf('~') >= 0) ? TryExpandShortFileName(ref builder, path) : (MemoryExtensions.Equals(builder.AsSpan(), path.AsSpan(), StringComparison.Ordinal) ? path : builder.ToString()));
14 builder.Dispose();
15 return result;
16 }
17
18 internal static string Normalize(ref ValueStringBuilder path)
19 {
20 Span<char> initialBuffer = stackalloc char[260];
21 ValueStringBuilder builder = new ValueStringBuilder(initialBuffer);
22 GetFullPathName(path.AsSpan(terminate: true), ref builder);
23 string result = ((builder.AsSpan().IndexOf('~') >= 0) ? TryExpandShortFileName(ref builder, null) : builder.ToString());
24 builder.Dispose();
25 return result;
26 }
27
28 private static void GetFullPathName(ReadOnlySpan<char> path, ref ValueStringBuilder builder)
29 {
30 uint fullPathNameW;
31 while ((fullPathNameW = Interop.Kernel32.GetFullPathNameW(ref MemoryMarshal.GetReference(path), (uint)builder.Capacity, ref builder.GetPinnableReference(), IntPtr.Zero)) > builder.Capacity)
32 {
33 builder.EnsureCapacity(checked((int)fullPathNameW));
34 }
35 if (fullPathNameW == 0)
36 {
37 int num = Marshal.GetLastWin32Error();
38 if (num == 0)
39 {
40 num = 161;
41 }
43 }
44 builder.Length = (int)fullPathNameW;
45 }
46
47 internal static int PrependDevicePathChars(ref ValueStringBuilder content, bool isDosUnc, ref ValueStringBuilder buffer)
48 {
49 int length = content.Length;
50 length += (isDosUnc ? 6 : 4);
51 buffer.EnsureCapacity(length + 1);
52 buffer.Length = 0;
53 if (isDosUnc)
54 {
55 buffer.Append("\\\\?\\UNC\\");
56 buffer.Append(content.AsSpan(2));
57 return 6;
58 }
59 buffer.Append("\\\\?\\");
60 buffer.Append(content.AsSpan());
61 return 4;
62 }
63
64 internal static string TryExpandShortFileName(ref ValueStringBuilder outputBuilder, string originalPath)
65 {
66 int rootLength = PathInternal.GetRootLength(outputBuilder.AsSpan());
67 bool flag = PathInternal.IsDevice(outputBuilder.AsSpan());
69 bool flag2 = false;
70 int num = 0;
71 bool flag3 = false;
72 if (flag)
73 {
74 buffer.Append(outputBuilder.AsSpan());
75 if (outputBuilder[2] == '.')
76 {
77 flag3 = true;
78 buffer[2] = '?';
79 }
80 }
81 else
82 {
83 flag2 = !PathInternal.IsDevice(outputBuilder.AsSpan()) && outputBuilder.Length > 1 && outputBuilder[0] == '\\' && outputBuilder[1] == '\\';
84 num = PrependDevicePathChars(ref outputBuilder, flag2, ref buffer);
85 }
86 rootLength += num;
87 int length = buffer.Length;
88 bool flag4 = false;
89 int num2 = buffer.Length - 1;
90 while (!flag4)
91 {
92 uint longPathNameW = Interop.Kernel32.GetLongPathNameW(ref buffer.GetPinnableReference(terminate: true), ref outputBuilder.GetPinnableReference(), (uint)outputBuilder.Capacity);
93 if (buffer[num2] == '\0')
94 {
95 buffer[num2] = '\\';
96 }
97 if (longPathNameW == 0)
98 {
99 int lastWin32Error = Marshal.GetLastWin32Error();
100 if (lastWin32Error != 2 && lastWin32Error != 3)
101 {
102 break;
103 }
104 num2--;
105 while (num2 > rootLength && buffer[num2] != '\\')
106 {
107 num2--;
108 }
109 if (num2 == rootLength)
110 {
111 break;
112 }
113 buffer[num2] = '\0';
114 }
115 else if (longPathNameW > outputBuilder.Capacity)
116 {
117 outputBuilder.EnsureCapacity(checked((int)longPathNameW));
118 }
119 else
120 {
121 flag4 = true;
122 outputBuilder.Length = checked((int)longPathNameW);
123 if (num2 < length - 1)
124 {
125 outputBuilder.Append(buffer.AsSpan(num2, buffer.Length - num2));
126 }
127 }
128 }
129 ref ValueStringBuilder reference = ref flag4 ? ref outputBuilder : ref buffer;
130 if (flag3)
131 {
132 reference[2] = '.';
133 }
134 if (flag2)
135 {
136 reference[6] = '\\';
137 }
138 ReadOnlySpan<char> span = reference.AsSpan(num);
139 string result = ((originalPath != null && MemoryExtensions.Equals(span, originalPath.AsSpan(), StringComparison.Ordinal)) ? originalPath : span.ToString());
140 buffer.Dispose();
141 return result;
142 }
143}
static uint GetFullPathNameW(ref char lpFileName, uint nBufferLength, ref char lpBuffer, IntPtr lpFilePart)
static uint GetLongPathNameW(ref char lpszShortPath, ref char lpszLongPath, uint cchBuffer)
static string Normalize(string path)
Definition PathHelper.cs:8
static string Normalize(ref ValueStringBuilder path)
Definition PathHelper.cs:18
static string TryExpandShortFileName(ref ValueStringBuilder outputBuilder, string originalPath)
Definition PathHelper.cs:64
static void GetFullPathName(ReadOnlySpan< char > path, ref ValueStringBuilder builder)
Definition PathHelper.cs:28
static int PrependDevicePathChars(ref ValueStringBuilder content, bool isDosUnc, ref ValueStringBuilder buffer)
Definition PathHelper.cs:47
static int GetRootLength(ReadOnlySpan< char > path)
static bool IsDevice(ReadOnlySpan< char > path)
static Exception GetExceptionForWin32Error(int errorCode, string path="")
static bool Equals(this ReadOnlySpan< char > span, ReadOnlySpan< char > other, StringComparison comparisonType)
static readonly IntPtr Zero
Definition IntPtr.cs:18
override string ToString()
ReadOnlySpan< char > AsSpan(bool terminate)