| File: Polyfills\StringExtensions.cs | Web Access |
| Project: src\msbuild\src\Framework\Microsoft.Build.Framework.csproj (Microsoft.Build.Framework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #if !NET using System; #endif using System.Diagnostics.CodeAnalysis; namespace Microsoft.Build; internal static class StringExtensions { /// <inheritdoc cref="string.IsNullOrEmpty(string)"/> public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value) => string.IsNullOrEmpty(value); /// <inheritdoc cref="string.IsNullOrWhiteSpace(string)"/> public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? value) => string.IsNullOrWhiteSpace(value); extension(string) { /// <summary> /// Allocates a string of the specified length filled with null characters. /// </summary> public static string FastAllocateString(int length) // This calls FastAllocateString in the runtime, with extra checks. => new('\0', length); #if !NET /// <summary> /// Creates a new string with a specific length and initializes it after creation by using /// the specified callback. /// </summary> /// <typeparam name="TState"> /// The type of the element to pass to <paramref name="action"/>. /// </typeparam> /// <param name="length">The length of the string to create.</param> /// <param name="state">The element to pass to <paramref name="action"/>.</param> /// <param name="action">The callback to initialize the string.</param> /// <returns> /// The created string. /// </returns> /// <remarks> /// <para> /// The initial content of the destination span passed to <paramref name="action"/> is undefined. /// Therefore, it is the delegate's responsibility to ensure that every element of the span is assigned. /// Otherwise, the resulting string could contain random characters. /// </para> /// <para> /// To support interop scenarios, the underlying buffer is guaranteed to be at least 1 greater than /// represented by the span parameter of the action callback. This additional index represents the /// null-terminator and, if written, that is the only value supported. Writing any value other than the /// null-terminator corrupts the string and is considered undefined behavior. /// </para> /// </remarks> public static unsafe string Create<TState>(int length, TState state, SpanAction<char, TState> action) { ArgumentNullException.ThrowIfNull(action); ArgumentOutOfRangeException.ThrowIfNegative(length); if (length == 0) { return string.Empty; } string result = FastAllocateString(length); fixed (char* p = result) { action(new Span<char>(p, length), state); } return result; } #endif } } #if !NET /// <summary> /// Encapsulates a method that receives a span of objects of type <typeparamref name="T"/> and a state /// object of type <typeparamref name="TArg"/>. /// </summary> /// <typeparam name="T">The type of the objects in the span.</typeparam> /// <typeparam name="TArg">The type of the object that represents the state.</typeparam> /// <param name="span">A span of objects of type <typeparamref name="T"/>.</param> /// <param name="arg">A state object of type <typeparamref name="TArg"/>.</param> /// <remarks> /// On modern .NET, this delegate is declared with an 'allows ref struct' constraint on <typeparamref name="TArg"/>. /// </remarks> internal delegate void SpanAction<T, in TArg>(Span<T> span, TArg arg); #endif