public static unsafe string Create <TState>(int length, TState state, SpanAction <char, TState> action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } if (length <= 0) { if (length == 0) { return(string.Empty); } throw new ArgumentOutOfRangeException(nameof(length)); } string result = new string('\0', length); fixed(char *r = result) { action(new Span <char>(r, length), state); } return(result); }
public static void Ctor_Validating_FromDelegate() { object expectedState = new object(); SpanAction <byte, object> spanAction = (span, actualState) => { Assert.Same(expectedState, actualState); Assert.NotEqual(0, span.Length); // shouldn't have been called for a zero-length span for (int i = 0; i < span.Length; i++) { Assert.Equal(0, span[i]); // should've been zero-inited span[i] = (byte)('a' + (i % 26)); // writes "abc...xyzabc...xyz..." } }; ArgumentException exception = Assert.Throws <ArgumentOutOfRangeException>(() => Utf8String.Create(-1, expectedState, spanAction)); Assert.Equal("length", exception.ParamName); exception = Assert.Throws <ArgumentNullException>(() => Utf8String.Create(10, expectedState, action: null)); Assert.Equal("action", exception.ParamName); Assert.Same(Utf8String.Empty, Utf8String.Create(0, expectedState, spanAction)); Assert.Equal(u8("abcde"), Utf8String.Create(5, expectedState, spanAction)); }
public static void Ctor_CreateRelaxed_FromDelegate() { object expectedState = new object(); SpanAction <byte, object> spanAction = (span, actualState) => { Assert.Same(expectedState, actualState); Assert.NotEqual(0, span.Length); // shouldn't have been called for a zero-length span for (int i = 0; i < span.Length; i++) { Assert.Equal(0, span[i]); // should've been zero-inited span[i] = 0xFF; // never a valid UTF-8 byte } }; ArgumentException exception = Assert.Throws <ArgumentOutOfRangeException>(() => Utf8String.CreateRelaxed(-1, expectedState, spanAction)); Assert.Equal("length", exception.ParamName); exception = Assert.Throws <ArgumentNullException>(() => Utf8String.CreateRelaxed(10, expectedState, action: null)); Assert.Equal("action", exception.ParamName); Assert.Same(Utf8String.Empty, Utf8String.CreateRelaxed(0, expectedState, spanAction)); Assert.Equal(u8("\uFFFD\uFFFD"), Utf8String.CreateRelaxed(2, expectedState, spanAction)); }
/// <summary> /// Creates a new <see cref="Utf8String"/> instance, allowing the provided delegate to populate the /// instance data of the returned object. /// </summary> /// <typeparam name="TState">Type of the state object provided to <paramref name="action"/>.</typeparam> /// <param name="length">The length, in bytes, of the <see cref="Utf8String"/> instance to create.</param> /// <param name="state">The state object to provide to <paramref name="action"/>.</param> /// <param name="action">The callback which will be invoked to populate the returned <see cref="Utf8String"/>.</param> /// <exception cref="ArgumentException"> /// Thrown if <paramref name="action"/> populates the buffer with ill-formed UTF-8 data. /// </exception> /// <remarks> /// The runtime will perform UTF-8 validation over the contents provided by the <paramref name="action"/> delegate. /// If an invalid UTF-8 subsequence is detected, an exception is thrown. /// </remarks> public static Utf8String Create <TState>(int length, TState state, SpanAction <byte, TState> action) { if (length < 0) { ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); } if (action is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action); } if (length == 0) { return(Empty); // special-case empty input } // Create and populate the Utf8String instance. // Can't use FastAllocateSkipZeroInit here because we're handing the raw buffer to user code. Utf8String newString = FastAllocate(length); action(newString.DangerousGetMutableSpan(), state); // Now perform validation. if (!Utf8Utility.IsWellFormedUtf8(newString.AsBytes())) { throw new ArgumentException( message: SR.Utf8String_CallbackProvidedMalformedData, paramName: nameof(action)); } return(newString); }
/// <summary> /// Creates a new <see cref="Utf8String"/> instance, allowing the provided delegate to populate the /// instance data of the returned object. /// </summary> /// <typeparam name="TState">Type of the state object provided to <paramref name="action"/>.</typeparam> /// <param name="length">The length, in bytes, of the <see cref="Utf8String"/> instance to create.</param> /// <param name="state">The state object to provide to <paramref name="action"/>.</param> /// <param name="action">The callback which will be invoked to populate the returned <see cref="Utf8String"/>.</param> /// <remarks> /// The runtime will perform UTF-8 validation over the contents provided by the <paramref name="action"/> delegate. /// If an invalid UTF-8 subsequence is detected, the invalid subsequence is replaced with <see cref="Rune.ReplacementChar"/> /// in the returned <see cref="Utf8String"/> instance. This could result in the returned <see cref="Utf8String"/> instance /// having a different byte length than specified by the <paramref name="length"/> parameter. /// </remarks> public static Utf8String CreateRelaxed <TState>(int length, TState state, SpanAction <byte, TState> action) { if (length < 0) { ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); } if (action is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action); } if (length == 0) { return(Empty); // special-case empty input } // Create and populate the Utf8String instance. // Can't use FastAllocateSkipZeroInit here because we're handing the raw buffer to user code. Utf8String newString = FastAllocate(length); action(newString.DangerousGetMutableSpan(), state); // Now perform validation and fixup. return(Utf8Utility.ValidateAndFixupUtf8String(newString)); }
private static void TestClampSpan <T>( int length, T min, T max, SpanAction <T, T, T> clampAction, Func <T, T, T, T> refClampFunc) where T : unmanaged, IComparable <T> { Span <T> actual = new T[length]; var r = new Random(); for (int i = 0; i < length; i++) { actual[i] = (T)Convert.ChangeType(r.Next(byte.MinValue, byte.MaxValue), typeof(T)); } Span <T> expected = new T[length]; actual.CopyTo(expected); for (int i = 0; i < expected.Length; i++) { ref T v = ref expected[i]; v = refClampFunc(v, min, max); }
public static string Create <TState>(int length, TState state, SpanAction <char, TState> action) { Span <char> span = length <= 256 ? stackalloc char[length] : new char[length]; action(span, state); return(span.ToString()); }
/// <summary> /// Allocates the specified amount of elements and perform an operation over them using a <see cref="Span{T}"/>. /// </summary> /// <typeparam name="T">Type of the allocated elements.</typeparam> /// <param name="elementCount">The number of elements to allocate.</param> /// <param name="stackAlloc">If <c>true</c> and the amount of elements is small the allocation may occur in the stack.</param> /// <param name="action">The action to perform over the elements using a span.</param> public unsafe void Borrow <T>(int elementCount, bool stackAlloc, SpanAction <T, int> action) where T : unmanaged { #if BIT64 const int bytesThreshold = 500000; #else const int bytesThreshold = 250000; #endif int totalBytes = sizeof(T) * elementCount; if (totalBytes > bytesThreshold && stackAlloc) { void *memBlock = stackalloc byte[totalBytes]; action(new Span <T>(memBlock, elementCount), elementCount); } else { void *memBlock = Allocate(totalBytes); try { action(new Span <T>(memBlock, elementCount), elementCount); } finally { Free(memBlock); } } }
public void WriteBitString <TState>( int byteLength, TState state, SpanAction <byte, TState> action, int unusedBitCount = 0) { WriteBitStringCore(Asn1Tag.PrimitiveBitString, byteLength, state, action, unusedBitCount); }
public static void Ctor_Validating_FromDelegate_ThrowsIfDelegateProvidesInvalidData() { SpanAction <byte, object> spanAction = (span, actualState) => { span[0] = 0xFF; // never a valid UTF-8 byte }; Assert.Throws <ArgumentException>(() => Utf8String.Create(10, new object(), spanAction)); }
public void WriteBitString <TState>( Asn1Tag tag, int byteLength, TState state, SpanAction <byte, TState> action, int unusedBitCount = 0) { CheckUniversalTag(tag, UniversalTagNumber.BitString); // Primitive or constructed, doesn't matter. WriteBitStringCore(tag, byteLength, state, action, unusedBitCount); }
/// <summary> /// Allocates the specified amount of elements and perform an operation over them using a <see cref="Span{T}"/>. /// </summary> /// <typeparam name="T">Type of the allocated elements.</typeparam> /// <param name="elementCount">The number of elements to allocate.</param> /// <param name="action">The action to perform over the elements using a span.</param> public unsafe void Borrow <T>(int elementCount, SpanAction <T, int> action) where T : unmanaged { void *memBlock = Allocate <T>(elementCount); try { action(new Span <T>(memBlock, elementCount), elementCount); } finally { Free(memBlock); } }
public static string CreateString <TState>(int length, TState state, SpanAction <char, TState> action) { var result = new string((char)0, length); unsafe { fixed(char *chars = result) { var charBuffer = new Span <char>(chars, result.Length); action(charBuffer, state); } } return(result); }
public static Utf8String Create <TState>( int length, TState state, SpanAction <byte, TState> action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } if (length == 0) { return(Empty); } var str = new Utf8String(length); action.Invoke(str._bytes, state); return(str); }
public static string Create <TState>(int length, TState state, SpanAction <char, TState> action) { ArgumentNullException.ThrowIfNull(action); if (length <= 0) { if (length == 0) { return(Empty); } throw new ArgumentOutOfRangeException(nameof(length)); } string result = FastAllocateString(length); action(new Span <char>(ref result.GetRawStringData(), length), state); return(result); }
public static string Create <T>(int length, T state, SpanAction <char, T> action) { #if NETSTANDARD2_0 unsafe { var str = new string((char)0, length); fixed(char *chars = str) { var span = new Span <char>(chars, length); action(span, state); } return(str); } #else return(string.Create(length, state, action)); #endif }
/// <summary> /// Utility function to apply a given <see cref="SpanAction{T, TArg}"/> to all <see cref="Destinations"/>. /// </summary> /// <param name="action">The action to execute on each elements.</param> private void ForEachDestination(SpanAction <SplitterDestination, int> action) { Span <SplitterDestination> temp = Destinations; int i = 0; while (true) { if (temp.IsEmpty) { break; } Span <SplitterDestination> next = temp[0].Next; action.Invoke(temp, i++); temp = next; } }
public ValueTask SetTypes(Type xType, Type yType) { if (!XTypes.Contains(xType) || !YTypes.Contains(yType)) { throw new InvalidOperationException("Unsupported data types."); } Cursor = 0; xSize = xType switch { Type t when t == typeof(DateTime) => sizeof(int), Type t when t == typeof(HighPrecTime) => sizeof(long), _ => System.Runtime.InteropServices.Marshal.SizeOf(xType) }; ySize = System.Runtime.InteropServices.Marshal.SizeOf(yType); xSerializer = GetSerializer(xType); ySerializer = GetSerializer(yType); return(default(ValueTask)); }
public static string BuildStringFromIndefiniteLengthTextString <TState>(int length, TState state, SpanAction <char, TState> action) => string.Create(length, state, action);
private void WriteBitStringCore <TState>( Asn1Tag tag, int byteLength, TState state, SpanAction <byte, TState> action, int unusedBitCount = 0) { if (byteLength == 0) { WriteBitStringCore(tag, ReadOnlySpan <byte> .Empty, unusedBitCount); return; } // T-REC-X.690-201508 sec 8.6.2.2 if (unusedBitCount < 0 || unusedBitCount > 7) { throw new ArgumentOutOfRangeException( nameof(unusedBitCount), unusedBitCount, SR.Cryptography_Asn_UnusedBitCountRange); } CheckDisposed(); int savedOffset = _offset; Span <byte> scratchSpace; byte[]? ensureNoExtraCopy = null; int expectedSize = 0; // T-REC-X.690-201508 sec 9.2 // // If it's not within a primitive segment, use the constructed encoding. // (>= instead of > because of the unused bit count byte) bool segmentedWrite = RuleSet == AsnEncodingRules.CER && byteLength >= AsnReader.MaxCERSegmentSize; if (segmentedWrite) { // Rather than call the callback multiple times, grow the buffer to allow // for enough space for the final output, then return a buffer where the last segment // is in the correct place. (Data will shift backwards to the right spot while writing // other segments). expectedSize = DetermineCerBitStringTotalLength(tag, byteLength); EnsureWriteCapacity(expectedSize); int overhead = expectedSize - byteLength; // Start writing where the last content byte is in the correct place, which is // after all of the overhead, but ending before the two byte end-of-contents marker. int scratchStart = overhead - 2; ensureNoExtraCopy = _buffer; scratchSpace = _buffer.AsSpan(scratchStart, byteLength); // Don't let gapped-writes be unpredictable. scratchSpace.Clear(); } else { WriteTag(tag.AsPrimitive()); // The unused bits byte requires +1. WriteLength(byteLength + 1); _buffer[_offset] = (byte)unusedBitCount; _offset++; scratchSpace = _buffer.AsSpan(_offset, byteLength); } action(scratchSpace, state); // T-REC-X.690-201508 sec 11.2 // // This could be ignored for BER, but since DER is more common and // it likely suggests a program error on the caller, leave it enabled for // BER for now. if (!CheckValidLastByte(scratchSpace[byteLength - 1], unusedBitCount)) { // Since we are restoring _offset we won't clear this on a grow or Dispose, // so clear it now. _offset = savedOffset; scratchSpace.Clear(); // TODO: Probably warrants a distinct message. throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } if (segmentedWrite) { WriteConstructedCerBitString(tag, scratchSpace, unusedBitCount); Debug.Assert(_offset - savedOffset == expectedSize, $"expected size was {expectedSize}, actual was {_offset - savedOffset}"); Debug.Assert(_buffer == ensureNoExtraCopy, $"_buffer was replaced during while writing a bit string via callback"); } else { _offset += byteLength; } }
public void Load(int dataLength, SpanAction <T> initialize, bool asPowerOfTwoTexture = true) { ArgumentNullException.ThrowIfNull(initialize); Load(dataLength, initialize,
/// <inheritdoc cref="string.Create{T}(int,T,SpanAction{char,T})"/> public static string CreateString <TState>(this int length, TState state, SpanAction <char, TState> action) => string.Create(length, state, action);
/// <summary> /// Creates a new <see cref="Utf8String"/> instance, allowing the provided delegate to populate the /// instance data of the returned object. Please see remarks for important safety information about /// this method. /// </summary> /// <typeparam name="TState">Type of the state object provided to <paramref name="action"/>.</typeparam> /// <param name="length">The length, in bytes, of the <see cref="Utf8String"/> instance to create.</param> /// <param name="state">The state object to provide to <paramref name="action"/>.</param> /// <param name="action">The callback which will be invoked to populate the returned <see cref="Utf8String"/>.</param> /// <remarks> /// This factory method can be used as an optimization to skip the validation step that /// <see cref="Create{TState}(int, TState, SpanAction{byte, TState})"/> normally performs. The contract /// of this method requires that <paramref name="action"/> populate the buffer with well-formed UTF-8 /// data, as <see cref="Utf8String"/> contractually guarantees that it contains only well-formed UTF-8 data, /// and runtime instability could occur if a caller violates this guarantee. /// </remarks> public static Utf8String UnsafeCreateWithoutValidation <TState>(int length, TState state, SpanAction <byte, TState> action) { if (length < 0) { ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); } if (action is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action); } if (length == 0) { return(Empty); // special-case empty input } // Create and populate the Utf8String instance. // Can't use FastAllocateSkipZeroInit here because we're handing the raw buffer to user code. Utf8String newString = FastAllocate(length); action(newString.DangerousGetMutableSpan(), state); // The line below is removed entirely in release builds. Debug.Assert(Utf8Utility.IsWellFormedUtf8(newString.AsBytes()), "Callback populated the buffer with ill-formed UTF-8 data."); return(newString); }
/// <summary> /// Shim for string.Create. Creates an array of chars, invokes <paramref name="action"/>, and then creates a new string from the array. /// </summary> public static string StringCreate <TState>(int length, TState state, SpanAction <char, TState> action) { char[] str = new char[length]; action(str, state); return(new string(str)); }
public static string BuildStringFromIndefiniteLengthTextString <TState>(int length, TState state, SpanAction <char, TState> action) { char[] arr = new char[length]; action(arr, state); return(new string(arr)); }