Ejemplo n.º 1
0
        /// <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);
                    }
                }
            }
        }
Ejemplo n.º 5
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);
        }