@@ -129,6 +129,33 @@ public static explicit operator string(UPath path)
129
129
/// </exception>
130
130
/// <exception cref="System.ArgumentException">If an error occurs while trying to combine paths.</exception>
131
131
public static UPath Combine ( UPath path1 , UPath path2 )
132
+ {
133
+ if ( TryGetAbsolute ( path1 , path2 , out var result ) )
134
+ {
135
+ return result ;
136
+ }
137
+
138
+ try
139
+ {
140
+ #if NET7_0_OR_GREATER
141
+ return string . Create ( path1 . FullName . Length + path2 . FullName . Length + 1 , new KeyValuePair < UPath , UPath > ( path1 , path2 ) , ( span , state ) =>
142
+ {
143
+ var ( left , right ) = state ;
144
+ left . FullName . AsSpan ( ) . CopyTo ( span ) ;
145
+ span [ left . FullName . Length ] = '/' ;
146
+ right . FullName . AsSpan ( ) . CopyTo ( span . Slice ( left . FullName . Length + 1 ) ) ;
147
+ } ) ;
148
+ #else
149
+ return new UPath ( $ "{ path1 . FullName } /{ path2 . FullName } ") ;
150
+ #endif
151
+ }
152
+ catch ( ArgumentException ex )
153
+ {
154
+ throw new ArgumentException ( $ "Unable to combine path `{ path1 } ` with `{ path2 } `", ex ) ;
155
+ }
156
+ }
157
+
158
+ private static bool TryGetAbsolute ( UPath path1 , UPath path2 , out UPath result )
132
159
{
133
160
if ( path1 . FullName is null )
134
161
throw new ArgumentNullException ( nameof ( path1 ) ) ;
@@ -138,26 +165,88 @@ public static UPath Combine(UPath path1, UPath path2)
138
165
139
166
// If the right path is absolute, it takes priority over path1
140
167
if ( path1 . IsEmpty || path2 . IsAbsolute )
141
- return path2 ;
142
-
143
- try
144
168
{
145
- return new UPath ( $ "{ path1 . FullName } /{ path2 . FullName } ") ;
146
- }
147
- catch ( ArgumentException ex )
148
- {
149
- throw new ArgumentException ( $ "Unable to combine path `{ path1 } ` with `{ path2 } `", ex ) ;
169
+ result = path2 ;
170
+ return true ;
150
171
}
172
+
173
+ result = default ;
174
+ return false ;
151
175
}
152
176
153
177
public static UPath Combine ( UPath path1 , UPath path2 , UPath path3 )
154
178
{
179
+ if ( TryGetAbsolute ( path1 , path2 , out var result ) )
180
+ {
181
+ return Combine ( result , path3 ) ;
182
+ }
183
+
184
+ if ( TryGetAbsolute ( path2 , path3 , out result ) )
185
+ {
186
+ return Combine ( path1 , result ) ;
187
+ }
188
+
189
+ #if NET7_0_OR_GREATER
190
+ return string . Create ( path1 . FullName . Length + path2 . FullName . Length + path3 . FullName . Length + 2 , ( path1 , path2 , path3 ) , ( span , state ) =>
191
+ {
192
+ var ( p1 , p2 , p3 ) = state ;
193
+ var remaining = span ;
194
+
195
+ p1 . FullName . AsSpan ( ) . CopyTo ( remaining ) ;
196
+ remaining [ p1 . FullName . Length ] = '/' ;
197
+ remaining = remaining . Slice ( p1 . FullName . Length + 1 ) ;
198
+
199
+ p2 . FullName . AsSpan ( ) . CopyTo ( remaining ) ;
200
+ remaining [ p2 . FullName . Length ] = '/' ;
201
+
202
+ remaining = remaining . Slice ( p2 . FullName . Length + 1 ) ;
203
+ p3 . FullName . AsSpan ( ) . CopyTo ( remaining ) ;
204
+ } ) ;
205
+ #else
155
206
return UPath . Combine ( UPath . Combine ( path1 , path2 ) , path3 ) ;
207
+ #endif
156
208
}
157
209
158
210
public static UPath Combine ( UPath path1 , UPath path2 , UPath path3 , UPath path4 )
159
211
{
160
- return UPath . Combine ( Combine ( path1 , path2 ) , Combine ( path3 , path4 ) ) ;
212
+ if ( TryGetAbsolute ( path1 , path2 , out var result ) )
213
+ {
214
+ return Combine ( result , path3 , path4 ) ;
215
+ }
216
+
217
+ if ( TryGetAbsolute ( path2 , path3 , out result ) )
218
+ {
219
+ return Combine ( path1 , result , path4 ) ;
220
+ }
221
+
222
+ if ( TryGetAbsolute ( path3 , path4 , out result ) )
223
+ {
224
+ return Combine ( path1 , path2 , result ) ;
225
+ }
226
+
227
+ #if NET7_0_OR_GREATER
228
+ return string . Create ( path1 . FullName . Length + path2 . FullName . Length + path3 . FullName . Length + path4 . FullName . Length + 3 , ( path1 , path2 , path3 , path4 ) , ( span , state ) =>
229
+ {
230
+ var ( p1 , p2 , p3 , p4 ) = state ;
231
+ var remaining = span ;
232
+
233
+ p1 . FullName . AsSpan ( ) . CopyTo ( remaining ) ;
234
+ remaining [ p1 . FullName . Length ] = '/' ;
235
+ remaining = remaining . Slice ( p1 . FullName . Length + 1 ) ;
236
+
237
+ p2 . FullName . AsSpan ( ) . CopyTo ( remaining ) ;
238
+ remaining [ p2 . FullName . Length ] = '/' ;
239
+ remaining = remaining . Slice ( p2 . FullName . Length + 1 ) ;
240
+
241
+ p3 . FullName . AsSpan ( ) . CopyTo ( remaining ) ;
242
+ remaining [ p3 . FullName . Length ] = '/' ;
243
+ remaining = remaining . Slice ( p3 . FullName . Length + 1 ) ;
244
+
245
+ p4 . FullName . AsSpan ( ) . CopyTo ( remaining ) ;
246
+ } ) ;
247
+ #else
248
+ return UPath . Combine ( UPath . Combine ( path1 , path2 ) , UPath . Combine ( path3 , path4 ) ) ;
249
+ #endif
161
250
}
162
251
163
252
public static UPath Combine ( params UPath [ ] paths )
0 commit comments