1
// Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System
.Diagnostics
;
9 public static partial class MemoryExtensions
12 /// Removes all leading and trailing occurrences of a specified element from the memory.
14 /// <param name="memory">The source memory from which the element is removed.</param>
15 /// <param name="trimElement">The specified element to look for and remove.</param>
16 public static Memory
<T
> Trim
<T
>(this Memory
<T
> memory
, T trimElement
)
17 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
18 where T
: IEquatable
<T
>
21 ReadOnlySpan
<T
> span
= memory
.Span
;
22 int start
= ClampStart(span
, trimElement
);
23 int length
= ClampEnd(span
, start
, trimElement
);
24 return memory
.Slice(start
, length
);
28 /// Removes all leading occurrences of a specified element from the memory.
30 /// <param name="memory">The source memory from which the element is removed.</param>
31 /// <param name="trimElement">The specified element to look for and remove.</param>
32 public static Memory
<T
> TrimStart
<T
>(this Memory
<T
> memory
, T trimElement
)
33 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
34 where T
: IEquatable
<T
>
36 => memory
.Slice(ClampStart(memory
.Span
, trimElement
));
39 /// Removes all trailing occurrences of a specified element from the memory.
41 /// <param name="memory">The source memory from which the element is removed.</param>
42 /// <param name="trimElement">The specified element to look for and remove.</param>
43 public static Memory
<T
> TrimEnd
<T
>(this Memory
<T
> memory
, T trimElement
)
44 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
45 where T
: IEquatable
<T
>
47 => memory
.Slice(0, ClampEnd(memory
.Span
, 0, trimElement
));
50 /// Removes all leading and trailing occurrences of a specified element from the memory.
52 /// <param name="memory">The source memory from which the element is removed.</param>
53 /// <param name="trimElement">The specified element to look for and remove.</param>
54 public static ReadOnlyMemory
<T
> Trim
<T
>(this ReadOnlyMemory
<T
> memory
, T trimElement
)
55 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
56 where T
: IEquatable
<T
>
59 ReadOnlySpan
<T
> span
= memory
.Span
;
60 int start
= ClampStart(span
, trimElement
);
61 int length
= ClampEnd(span
, start
, trimElement
);
62 return memory
.Slice(start
, length
);
66 /// Removes all leading occurrences of a specified element from the memory.
68 /// <param name="memory">The source memory from which the element is removed.</param>
69 /// <param name="trimElement">The specified element to look for and remove.</param>
70 public static ReadOnlyMemory
<T
> TrimStart
<T
>(this ReadOnlyMemory
<T
> memory
, T trimElement
)
71 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
72 where T
: IEquatable
<T
>
74 => memory
.Slice(ClampStart(memory
.Span
, trimElement
));
77 /// Removes all trailing occurrences of a specified element from the memory.
79 /// <param name="memory">The source memory from which the element is removed.</param>
80 /// <param name="trimElement">The specified element to look for and remove.</param>
81 public static ReadOnlyMemory
<T
> TrimEnd
<T
>(this ReadOnlyMemory
<T
> memory
, T trimElement
)
82 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
83 where T
: IEquatable
<T
>
85 => memory
.Slice(0, ClampEnd(memory
.Span
, 0, trimElement
));
88 /// Removes all leading and trailing occurrences of a specified element from the span.
90 /// <param name="span">The source span from which the element is removed.</param>
91 /// <param name="trimElement">The specified element to look for and remove.</param>
92 public static Span
<T
> Trim
<T
>(this Span
<T
> span
, T trimElement
)
93 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
94 where T
: IEquatable
<T
>
97 int start
= ClampStart(span
, trimElement
);
98 int length
= ClampEnd(span
, start
, trimElement
);
99 return span
.Slice(start
, length
);
103 /// Removes all leading occurrences of a specified element from the span.
105 /// <param name="span">The source span from which the element is removed.</param>
106 /// <param name="trimElement">The specified element to look for and remove.</param>
107 public static Span
<T
> TrimStart
<T
>(this Span
<T
> span
, T trimElement
)
108 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
109 where T
: IEquatable
<T
>
111 => span
.Slice(ClampStart(span
, trimElement
));
114 /// Removes all trailing occurrences of a specified element from the span.
116 /// <param name="span">The source span from which the element is removed.</param>
117 /// <param name="trimElement">The specified element to look for and remove.</param>
118 public static Span
<T
> TrimEnd
<T
>(this Span
<T
> span
, T trimElement
)
119 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
120 where T
: IEquatable
<T
>
122 => span
.Slice(0, ClampEnd(span
, 0, trimElement
));
125 /// Removes all leading and trailing occurrences of a specified element from the span.
127 /// <param name="span">The source span from which the element is removed.</param>
128 /// <param name="trimElement">The specified element to look for and remove.</param>
129 public static ReadOnlySpan
<T
> Trim
<T
>(this ReadOnlySpan
<T
> span
, T trimElement
)
130 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
131 where T
: IEquatable
<T
>
134 int start
= ClampStart(span
, trimElement
);
135 int length
= ClampEnd(span
, start
, trimElement
);
136 return span
.Slice(start
, length
);
140 /// Removes all leading occurrences of a specified element from the span.
142 /// <param name="span">The source span from which the element is removed.</param>
143 /// <param name="trimElement">The specified element to look for and remove.</param>
144 public static ReadOnlySpan
<T
> TrimStart
<T
>(this ReadOnlySpan
<T
> span
, T trimElement
)
145 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
146 where T
: IEquatable
<T
>
148 => span
.Slice(ClampStart(span
, trimElement
));
151 /// Removes all trailing occurrences of a specified element from the span.
153 /// <param name="span">The source span from which the element is removed.</param>
154 /// <param name="trimElement">The specified element to look for and remove.</param>
155 public static ReadOnlySpan
<T
> TrimEnd
<T
>(this ReadOnlySpan
<T
> span
, T trimElement
)
156 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
157 where T
: IEquatable
<T
>
159 => span
.Slice(0, ClampEnd(span
, 0, trimElement
));
162 /// Delimits all leading occurrences of a specified element from the span.
164 /// <param name="span">The source span from which the element is removed.</param>
165 /// <param name="trimElement">The specified element to look for and remove.</param>
166 private static int ClampStart
<T
>(ReadOnlySpan
<T
> span
, T trimElement
)
167 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
168 where T
: IEquatable
<T
>
173 if (trimElement
!= null)
175 for (; start
< span
.Length
; start
++)
177 if (!trimElement
.Equals(span
[start
]))
185 for (; start
< span
.Length
; start
++)
187 if (span
[start
] != null)
198 /// Delimits all trailing occurrences of a specified element from the span.
200 /// <param name="span">The source span from which the element is removed.</param>
201 /// <param name="start">The start index from which to being searching.</param>
202 /// <param name="trimElement">The specified element to look for and remove.</param>
203 private static int ClampEnd
<T
>(ReadOnlySpan
<T
> span
, int start
, T trimElement
)
204 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
205 where T
: IEquatable
<T
>
208 // Initially, start==len==0. If ClampStart trims all, start==len
209 Debug
.Assert((uint)start
<= span
.Length
);
211 int end
= span
.Length
- 1;
213 if (trimElement
!= null)
215 for (; end
>= start
; end
--)
217 if (!trimElement
.Equals(span
[end
]))
225 for (; end
>= start
; end
--)
227 if (span
[end
] != null)
234 return end
- start
+ 1;
238 /// Removes all leading and trailing occurrences of a set of elements specified
239 /// in a readonly span from the memory.
241 /// <param name="memory">The source memory from which the elements are removed.</param>
242 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
243 /// <remarks>If <paramref name="trimElements"/> is empty, the memory is returned unaltered.</remarks>
244 public static Memory
<T
> Trim
<T
>(this Memory
<T
> memory
, ReadOnlySpan
<T
> trimElements
)
245 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
246 where T
: IEquatable
<T
>
249 if (trimElements
.Length
> 1)
251 ReadOnlySpan
<T
> span
= memory
.Span
;
252 int start
= ClampStart(span
, trimElements
);
253 int length
= ClampEnd(span
, start
, trimElements
);
254 return memory
.Slice(start
, length
);
257 if (trimElements
.Length
== 1)
259 return Trim(memory
, trimElements
[0]);
266 /// Removes all leading occurrences of a set of elements specified
267 /// in a readonly span from the memory.
269 /// <param name="memory">The source memory from which the elements are removed.</param>
270 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
271 /// <remarks>If <paramref name="trimElements"/> is empty, the memory is returned unaltered.</remarks>
272 public static Memory
<T
> TrimStart
<T
>(this Memory
<T
> memory
, ReadOnlySpan
<T
> trimElements
)
273 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
274 where T
: IEquatable
<T
>
277 if (trimElements
.Length
> 1)
279 return memory
.Slice(ClampStart(memory
.Span
, trimElements
));
282 if (trimElements
.Length
== 1)
284 return TrimStart(memory
, trimElements
[0]);
291 /// Removes all trailing occurrences of a set of elements specified
292 /// in a readonly span from the memory.
294 /// <param name="memory">The source memory from which the elements are removed.</param>
295 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
296 /// <remarks>If <paramref name="trimElements"/> is empty, the memory is returned unaltered.</remarks>
297 public static Memory
<T
> TrimEnd
<T
>(this Memory
<T
> memory
, ReadOnlySpan
<T
> trimElements
)
298 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
299 where T
: IEquatable
<T
>
302 if (trimElements
.Length
> 1)
304 return memory
.Slice(0, ClampEnd(memory
.Span
, 0, trimElements
));
307 if (trimElements
.Length
== 1)
309 return TrimEnd(memory
, trimElements
[0]);
316 /// Removes all leading and trailing occurrences of a set of elements specified
317 /// in a readonly span from the memory.
319 /// <param name="memory">The source memory from which the elements are removed.</param>
320 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
321 /// <remarks>If <paramref name="trimElements"/> is empty, the memory is returned unaltered.</remarks>
322 public static ReadOnlyMemory
<T
> Trim
<T
>(this ReadOnlyMemory
<T
> memory
, ReadOnlySpan
<T
> trimElements
)
323 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
324 where T
: IEquatable
<T
>
327 if (trimElements
.Length
> 1)
329 ReadOnlySpan
<T
> span
= memory
.Span
;
330 int start
= ClampStart(span
, trimElements
);
331 int length
= ClampEnd(span
, start
, trimElements
);
332 return memory
.Slice(start
, length
);
335 if (trimElements
.Length
== 1)
337 return Trim(memory
, trimElements
[0]);
344 /// Removes all leading occurrences of a set of elements specified
345 /// in a readonly span from the memory.
347 /// <param name="memory">The source memory from which the elements are removed.</param>
348 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
349 /// <remarks>If <paramref name="trimElements"/> is empty, the memory is returned unaltered.</remarks>
350 public static ReadOnlyMemory
<T
> TrimStart
<T
>(this ReadOnlyMemory
<T
> memory
, ReadOnlySpan
<T
> trimElements
)
351 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
352 where T
: IEquatable
<T
>
355 if (trimElements
.Length
> 1)
357 return memory
.Slice(ClampStart(memory
.Span
, trimElements
));
360 if (trimElements
.Length
== 1)
362 return TrimStart(memory
, trimElements
[0]);
369 /// Removes all trailing occurrences of a set of elements specified
370 /// in a readonly span from the memory.
372 /// <param name="memory">The source memory from which the elements are removed.</param>
373 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
374 /// <remarks>If <paramref name="trimElements"/> is empty, the memory is returned unaltered.</remarks>
375 public static ReadOnlyMemory
<T
> TrimEnd
<T
>(this ReadOnlyMemory
<T
> memory
, ReadOnlySpan
<T
> trimElements
)
376 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
377 where T
: IEquatable
<T
>
380 if (trimElements
.Length
> 1)
382 return memory
.Slice(0, ClampEnd(memory
.Span
, 0, trimElements
));
385 if (trimElements
.Length
== 1)
387 return TrimEnd(memory
, trimElements
[0]);
394 /// Removes all leading and trailing occurrences of a set of elements specified
395 /// in a readonly span from the span.
397 /// <param name="span">The source span from which the elements are removed.</param>
398 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
399 /// <remarks>If <paramref name="trimElements"/> is empty, the span is returned unaltered.</remarks>
400 public static Span
<T
> Trim
<T
>(this Span
<T
> span
, ReadOnlySpan
<T
> trimElements
)
401 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
402 where T
: IEquatable
<T
>
405 if (trimElements
.Length
> 1)
407 int start
= ClampStart(span
, trimElements
);
408 int length
= ClampEnd(span
, start
, trimElements
);
409 return span
.Slice(start
, length
);
412 if (trimElements
.Length
== 1)
414 return Trim(span
, trimElements
[0]);
421 /// Removes all leading occurrences of a set of elements specified
422 /// in a readonly span from the span.
424 /// <param name="span">The source span from which the elements are removed.</param>
425 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
426 /// <remarks>If <paramref name="trimElements"/> is empty, the span is returned unaltered.</remarks>
427 public static Span
<T
> TrimStart
<T
>(this Span
<T
> span
, ReadOnlySpan
<T
> trimElements
)
428 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
429 where T
: IEquatable
<T
>
432 if (trimElements
.Length
> 1)
434 return span
.Slice(ClampStart(span
, trimElements
));
437 if (trimElements
.Length
== 1)
439 return TrimStart(span
, trimElements
[0]);
446 /// Removes all trailing occurrences of a set of elements specified
447 /// in a readonly span from the span.
449 /// <param name="span">The source span from which the elements are removed.</param>
450 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
451 /// <remarks>If <paramref name="trimElements"/> is empty, the span is returned unaltered.</remarks>
452 public static Span
<T
> TrimEnd
<T
>(this Span
<T
> span
, ReadOnlySpan
<T
> trimElements
)
453 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
454 where T
: IEquatable
<T
>
457 if (trimElements
.Length
> 1)
459 return span
.Slice(0, ClampEnd(span
, 0, trimElements
));
462 if (trimElements
.Length
== 1)
464 return TrimEnd(span
, trimElements
[0]);
471 /// Removes all leading and trailing occurrences of a set of elements specified
472 /// in a readonly span from the span.
474 /// <param name="span">The source span from which the elements are removed.</param>
475 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
476 /// <remarks>If <paramref name="trimElements"/> is empty, the span is returned unaltered.</remarks>
477 public static ReadOnlySpan
<T
> Trim
<T
>(this ReadOnlySpan
<T
> span
, ReadOnlySpan
<T
> trimElements
)
478 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
479 where T
: IEquatable
<T
>
482 if (trimElements
.Length
> 1)
484 int start
= ClampStart(span
, trimElements
);
485 int length
= ClampEnd(span
, start
, trimElements
);
486 return span
.Slice(start
, length
);
489 if (trimElements
.Length
== 1)
491 return Trim(span
, trimElements
[0]);
498 /// Removes all leading occurrences of a set of elements specified
499 /// in a readonly span from the span.
501 /// <param name="span">The source span from which the elements are removed.</param>
502 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
503 /// <remarks>If <paramref name="trimElements"/> is empty, the span is returned unaltered.</remarks>
504 public static ReadOnlySpan
<T
> TrimStart
<T
>(this ReadOnlySpan
<T
> span
, ReadOnlySpan
<T
> trimElements
)
505 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
506 where T
: IEquatable
<T
>
509 if (trimElements
.Length
> 1)
511 return span
.Slice(ClampStart(span
, trimElements
));
514 if (trimElements
.Length
== 1)
516 return TrimStart(span
, trimElements
[0]);
523 /// Removes all trailing occurrences of a set of elements specified
524 /// in a readonly span from the span.
526 /// <param name="span">The source span from which the elements are removed.</param>
527 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
528 /// <remarks>If <paramref name="trimElements"/> is empty, the span is returned unaltered.</remarks>
529 public static ReadOnlySpan
<T
> TrimEnd
<T
>(this ReadOnlySpan
<T
> span
, ReadOnlySpan
<T
> trimElements
)
530 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
531 where T
: IEquatable
<T
>
534 if (trimElements
.Length
> 1)
536 return span
.Slice(0, ClampEnd(span
, 0, trimElements
));
539 if (trimElements
.Length
== 1)
541 return TrimEnd(span
, trimElements
[0]);
548 /// Delimits all leading occurrences of a set of elements specified
549 /// in a readonly span from the span.
551 /// <param name="span">The source span from which the elements are removed.</param>
552 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
553 private static int ClampStart
<T
>(ReadOnlySpan
<T
> span
, ReadOnlySpan
<T
> trimElements
)
554 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
555 where T
: IEquatable
<T
>
559 for (; start
< span
.Length
; start
++)
561 if (!trimElements
.Contains(span
[start
]))
571 /// Delimits all trailing occurrences of a set of elements specified
572 /// in a readonly span from the span.
574 /// <param name="span">The source span from which the elements are removed.</param>
575 /// <param name="start">The start index from which to being searching.</param>
576 /// <param name="trimElements">The span which contains the set of elements to remove.</param>
577 private static int ClampEnd
<T
>(ReadOnlySpan
<T
> span
, int start
, ReadOnlySpan
<T
> trimElements
)
578 #nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
579 where T
: IEquatable
<T
>
582 // Initially, start==len==0. If ClampStart trims all, start==len
583 Debug
.Assert((uint)start
<= span
.Length
);
585 int end
= span
.Length
- 1;
586 for (; end
>= start
; end
--)
588 if (!trimElements
.Contains(span
[end
]))
594 return end
- start
+ 1;
598 /// Removes all leading and trailing white-space characters from the memory.
600 /// <param name="memory">The source memory from which the characters are removed.</param>
601 public static Memory
<char> Trim(this Memory
<char> memory
)
603 ReadOnlySpan
<char> span
= memory
.Span
;
604 int start
= ClampStart(span
);
605 int length
= ClampEnd(span
, start
);
606 return memory
.Slice(start
, length
);
610 /// Removes all leading white-space characters from the memory.
612 /// <param name="memory">The source memory from which the characters are removed.</param>
613 public static Memory
<char> TrimStart(this Memory
<char> memory
)
614 => memory
.Slice(ClampStart(memory
.Span
));
617 /// Removes all trailing white-space characters from the memory.
619 /// <param name="memory">The source memory from which the characters are removed.</param>
620 public static Memory
<char> TrimEnd(this Memory
<char> memory
)
621 => memory
.Slice(0, ClampEnd(memory
.Span
, 0));
624 /// Removes all leading and trailing white-space characters from the memory.
626 /// <param name="memory">The source memory from which the characters are removed.</param>
627 public static ReadOnlyMemory
<char> Trim(this ReadOnlyMemory
<char> memory
)
629 ReadOnlySpan
<char> span
= memory
.Span
;
630 int start
= ClampStart(span
);
631 int length
= ClampEnd(span
, start
);
632 return memory
.Slice(start
, length
);
636 /// Removes all leading white-space characters from the memory.
638 /// <param name="memory">The source memory from which the characters are removed.</param>
639 public static ReadOnlyMemory
<char> TrimStart(this ReadOnlyMemory
<char> memory
)
640 => memory
.Slice(ClampStart(memory
.Span
));
643 /// Removes all trailing white-space characters from the memory.
645 /// <param name="memory">The source memory from which the characters are removed.</param>
646 public static ReadOnlyMemory
<char> TrimEnd(this ReadOnlyMemory
<char> memory
)
647 => memory
.Slice(0, ClampEnd(memory
.Span
, 0));
650 /// Removes all leading and trailing white-space characters from the span.
652 /// <param name="span">The source span from which the characters are removed.</param>
653 public static ReadOnlySpan
<char> Trim(this ReadOnlySpan
<char> span
)
656 for (; start
< span
.Length
; start
++)
658 if (!char.IsWhiteSpace(span
[start
]))
664 int end
= span
.Length
- 1;
665 for (; end
> start
; end
--)
667 if (!char.IsWhiteSpace(span
[end
]))
673 return span
.Slice(start
, end
- start
+ 1);
677 /// Removes all leading white-space characters from the span.
679 /// <param name="span">The source span from which the characters are removed.</param>
680 public static ReadOnlySpan
<char> TrimStart(this ReadOnlySpan
<char> span
)
683 for (; start
< span
.Length
; start
++)
685 if (!char.IsWhiteSpace(span
[start
]))
691 return span
.Slice(start
);
695 /// Removes all trailing white-space characters from the span.
697 /// <param name="span">The source span from which the characters are removed.</param>
698 public static ReadOnlySpan
<char> TrimEnd(this ReadOnlySpan
<char> span
)
700 int end
= span
.Length
- 1;
701 for (; end
>= 0; end
--)
703 if (!char.IsWhiteSpace(span
[end
]))
709 return span
.Slice(0, end
+ 1);
713 /// Removes all leading and trailing occurrences of a specified character from the span.
715 /// <param name="span">The source span from which the character is removed.</param>
716 /// <param name="trimChar">The specified character to look for and remove.</param>
717 public static ReadOnlySpan
<char> Trim(this ReadOnlySpan
<char> span
, char trimChar
)
720 for (; start
< span
.Length
; start
++)
722 if (span
[start
] != trimChar
)
728 int end
= span
.Length
- 1;
729 for (; end
> start
; end
--)
731 if (span
[end
] != trimChar
)
737 return span
.Slice(start
, end
- start
+ 1);
741 /// Removes all leading occurrences of a specified character from the span.
743 /// <param name="span">The source span from which the character is removed.</param>
744 /// <param name="trimChar">The specified character to look for and remove.</param>
745 public static ReadOnlySpan
<char> TrimStart(this ReadOnlySpan
<char> span
, char trimChar
)
748 for (; start
< span
.Length
; start
++)
750 if (span
[start
] != trimChar
)
756 return span
.Slice(start
);
760 /// Removes all trailing occurrences of a specified character from the span.
762 /// <param name="span">The source span from which the character is removed.</param>
763 /// <param name="trimChar">The specified character to look for and remove.</param>
764 public static ReadOnlySpan
<char> TrimEnd(this ReadOnlySpan
<char> span
, char trimChar
)
766 int end
= span
.Length
- 1;
767 for (; end
>= 0; end
--)
769 if (span
[end
] != trimChar
)
775 return span
.Slice(0, end
+ 1);
779 /// Removes all leading and trailing occurrences of a set of characters specified
780 /// in a readonly span from the span.
782 /// <param name="span">The source span from which the characters are removed.</param>
783 /// <param name="trimChars">The span which contains the set of characters to remove.</param>
784 /// <remarks>If <paramref name="trimChars"/> is empty, white-space characters are removed instead.</remarks>
785 public static ReadOnlySpan
<char> Trim(this ReadOnlySpan
<char> span
, ReadOnlySpan
<char> trimChars
)
786 => span
.TrimStart(trimChars
).TrimEnd(trimChars
);
789 /// Removes all leading occurrences of a set of characters specified
790 /// in a readonly span from the span.
792 /// <param name="span">The source span from which the characters are removed.</param>
793 /// <param name="trimChars">The span which contains the set of characters to remove.</param>
794 /// <remarks>If <paramref name="trimChars"/> is empty, white-space characters are removed instead.</remarks>
795 public static ReadOnlySpan
<char> TrimStart(this ReadOnlySpan
<char> span
, ReadOnlySpan
<char> trimChars
)
797 if (trimChars
.IsEmpty
)
799 return span
.TrimStart();
803 for (; start
< span
.Length
; start
++)
805 for (int i
= 0; i
< trimChars
.Length
; i
++)
807 if (span
[start
] == trimChars
[i
])
818 return span
.Slice(start
);
822 /// Removes all trailing occurrences of a set of characters specified
823 /// in a readonly span from the span.
825 /// <param name="span">The source span from which the characters are removed.</param>
826 /// <param name="trimChars">The span which contains the set of characters to remove.</param>
827 /// <remarks>If <paramref name="trimChars"/> is empty, white-space characters are removed instead.</remarks>
828 public static ReadOnlySpan
<char> TrimEnd(this ReadOnlySpan
<char> span
, ReadOnlySpan
<char> trimChars
)
830 if (trimChars
.IsEmpty
)
832 return span
.TrimEnd();
835 int end
= span
.Length
- 1;
836 for (; end
>= 0; end
--)
838 for (int i
= 0; i
< trimChars
.Length
; i
++)
840 if (span
[end
] == trimChars
[i
])
851 return span
.Slice(0, end
+ 1);
855 /// Removes all leading and trailing white-space characters from the span.
857 /// <param name="span">The source span from which the characters are removed.</param>
858 public static Span
<char> Trim(this Span
<char> span
)
860 int start
= ClampStart(span
);
861 int length
= ClampEnd(span
, start
);
862 return span
.Slice(start
, length
);
866 /// Removes all leading white-space characters from the span.
868 /// <param name="span">The source span from which the characters are removed.</param>
869 public static Span
<char> TrimStart(this Span
<char> span
)
870 => span
.Slice(ClampStart(span
));
873 /// Removes all trailing white-space characters from the span.
875 /// <param name="span">The source span from which the characters are removed.</param>
876 public static Span
<char> TrimEnd(this Span
<char> span
)
877 => span
.Slice(0, ClampEnd(span
, 0));
880 /// Delimits all leading occurrences of whitespace charecters from the span.
882 /// <param name="span">The source span from which the characters are removed.</param>
883 private static int ClampStart(ReadOnlySpan
<char> span
)
887 for (; start
< span
.Length
; start
++)
889 if (!char.IsWhiteSpace(span
[start
]))
899 /// Delimits all trailing occurrences of whitespace charecters from the span.
901 /// <param name="span">The source span from which the characters are removed.</param>
902 /// <param name="start">The start index from which to being searching.</param>
903 private static int ClampEnd(ReadOnlySpan
<char> span
, int start
)
905 // Initially, start==len==0. If ClampStart trims all, start==len
906 Debug
.Assert((uint)start
<= span
.Length
);
908 int end
= span
.Length
- 1;
910 for (; end
>= start
; end
--)
912 if (!char.IsWhiteSpace(span
[end
]))
918 return end
- start
+ 1;