/// <summary> /// Parses a <see cref="ulong"/> from the specified <see cref="ReadableBuffer"/> /// </summary> /// <param name="buffer">The <see cref="ReadableBuffer"/> to parse</param> public static ulong GetUInt64(this ReadableBuffer buffer) { ulong value; if (Utf8Parser.TryParseUInt64(buffer.First.Span, out value)) { return(value); } if (buffer.IsSingleSpan) // no more data to parse { throw new InvalidOperationException(); } var bufferLength = buffer.Length; int toParseLength = 21; // longest invariant UTF8 UInt64 + 1 (so we know there is a delimiter at teh end) if (bufferLength < 21) { toParseLength = (int)bufferLength; } Span <byte> toParseBuffer = stackalloc byte[toParseLength]; buffer.CopyTo(toParseBuffer); if (Utf8Parser.TryParseUInt64(toParseBuffer, out value)) { return(value); } throw new InvalidOperationException(); }
public static bool TryParseUInt64(Utf8Span str, out ulong val) { if (!Utf8Parser.TryParseUInt64(str, out val, out var consumed) || consumed != str.Length()) { return(false); } return(true); }
public static ulong ParseUInt64(Utf8Span str) { if (!Utf8Parser.TryParseUInt64(str.Bytes, out var value, out var consumed)) { throw new FormatException(); } if (consumed != str.Length()) { throw new FormatException(); } return(value); }
[InlineData("0")] // min value private unsafe static void PrimitiveParserByteSpanToUInt64(string text) { byte[] utf8ByteArray = Text.Encoding.UTF8.GetBytes(text); ReadOnlySpan <byte> utf8ByteSpan = new ReadOnlySpan <byte>(utf8ByteArray); foreach (var iteration in Benchmark.Iterations) { using (iteration.StartMeasurement()) { for (int i = 0; i < TestHelper.LoadIterations; i++) { ulong value; Utf8Parser.TryParseUInt64(utf8ByteSpan, out value); TestHelper.DoNotIgnore(value, 0); } } } }
public static bool TryParseUInt64 <T>(this T bufferSequence, out ulong value, out int consumed) where T : ISequence <ReadOnlyMemory <byte> > { value = default; consumed = default; Position position = Position.First; // Fetch the first segment ReadOnlyMemory <byte> first; if (!bufferSequence.TryGet(ref position, out first)) { return(false); } // Attempt to parse the first segment. If it works (and it should in most cases), then return success. bool parsed = Utf8Parser.TryParseUInt64(first.Span, out value, out consumed); if (parsed && consumed < first.Length) { return(true); } // Apparently the we need data from the second segment to succesfully parse, and so fetch the second segment. ReadOnlyMemory <byte> second; if (!bufferSequence.TryGet(ref position, out second)) { // if there is no second segment and the first parsed succesfully, return the result of the parsing. if (parsed) { return(true); } return(false); } // Combine the first, the second, and potentially more segments into a stack allocated buffer if (first.Length < StackBufferSize) { Span <byte> destination = stackalloc byte[StackBufferSize]; first.Span.CopyTo(destination); var free = destination.Slice(first.Length); if (second.Length > free.Length) { second = second.Slice(0, free.Length); } second.Span.CopyTo(free); free = free.Slice(second.Length); ReadOnlyMemory <byte> next; while (free.Length > 0) { if (bufferSequence.TryGet(ref position, out next)) { if (next.Length > free.Length) { next = next.Slice(0, free.Length); } next.Span.CopyTo(free); free = free.Slice(next.Length); } else { break; } } var combinedStackSpan = destination.Slice(0, StackBufferSize - free.Length); // if the stack allocated buffer parsed succesfully (and for uint it should always do), then return success. if (Utf8Parser.TryParseUInt64(combinedStackSpan, out value, out consumed)) { if (consumed < combinedStackSpan.Length || combinedStackSpan.Length < StackBufferSize) { return(true); } } } // for invariant culture, we should never reach this point, as invariant uint text is never longer than 127 bytes. // I left this code here, as we will need it for custom cultures and possibly when we shrink the stack allocated buffer. var combinedSpan = bufferSequence.ToSpan(); if (!Utf8Parser.TryParseUInt64(combinedSpan, out value, out consumed)) { return(false); } return(true); }