public static bool TryParseUInt32 <TMultispan>(this TMultispan bytes, EncodingData encoding, out uint value, out int consumed) where TMultispan : ISequence <Span <byte> > { Position position = Position.BeforeFirst; var first = bytes.TryGetItem(ref position); if (!position.IsValid) { throw new ArgumentException("bytes cannot be empty"); } if (!PrimitiveParser.TryParse(first, EncodingData.Encoding.Utf8, out value, out consumed)) { return(false); // TODO: maybe we should continue in some cases, e.g. if the first span ends in a decimal separator // ... cont, maybe consumed could be set even if TryParse returns false } if (position.IsEnd || first.Length > consumed) { return(true); } var second = bytes.TryGetItem(ref position); Span <byte> temp; int numberOfBytesFromSecond = second.Length; if (numberOfBytesFromSecond > 64) { numberOfBytesFromSecond = 64; } var tempBufferLength = first.Length + numberOfBytesFromSecond; if (tempBufferLength > 128) { temp = new byte[tempBufferLength]; } else { unsafe { byte *data = stackalloc byte[tempBufferLength]; temp = new Span <byte>(data, tempBufferLength); } } first.TryCopyTo(temp); second.Slice(0, numberOfBytesFromSecond).TryCopyTo(temp.Slice(first.Length)); if (!PrimitiveParser.TryParse(temp, EncodingData.Encoding.Utf8, out value, out consumed)) { return(false); } if (position.IsEnd || temp.Length > consumed) { return(true); } throw new NotImplementedException(); }
public bool TryParseUInt64(out ulong value) { int consumed; var unread = Unread; if (PrimitiveParser.TryParseUInt64(unread, out value, out consumed, default(TextFormat), _encoder)) { if (unread.Length > consumed) { _currentSegmentIndex += consumed; return(true); } } unsafe { byte *temp = stackalloc byte[32]; var tempSpan = new Span <byte>(temp, 32); var copied = CopyTo(tempSpan); if (PrimitiveParser.TryParseUInt64(tempSpan.Slice(0, copied), out value, out consumed, 'G', _encoder)) { Advance(consumed); return(true); } } return(false); }
public static JsonObjectType GetType(ref ReadOnlySpan <char> content) { JsonTokenType tokenType = JsonToken.GetType(content); switch (tokenType) { case JsonTokenType.ArrayStart: return(JsonObjectType.Array); case JsonTokenType.ObjectStart: return(JsonObjectType.Object); case JsonTokenType.NameBoundary: return(JsonObjectType.String); case JsonTokenType.Unknown: if (PrimitiveParser.IsPrimitive(content)) { return(JsonObjectType.Primitive); } break; } throw new InvalidOperationException("Unsupported token type."); }
/// <summary> /// Parses a <see cref="uint"/> from the specified <see cref="ReadableBuffer"/> /// </summary> /// <param name="buffer">The <see cref="ReadableBuffer"/> to parse</param> public unsafe static uint GetUInt32(this ReadableBuffer buffer) { ReadOnlySpan <byte> textSpan; if (buffer.IsSingleSpan) { // It fits! textSpan = buffer.First.Span; } else if (buffer.Length < 128) // REVIEW: What's a good number { var data = stackalloc byte[128]; var destination = new Span <byte>(data, 128); buffer.CopyTo(destination); textSpan = destination.Slice(0, buffer.Length); } else { // Heap allocated copy to parse into array (should be rare) textSpan = new ReadOnlySpan <byte>(buffer.ToArray()); } uint value; var utf8Buffer = new Utf8String(textSpan); if (!PrimitiveParser.TryParseUInt32(utf8Buffer, out value)) { throw new InvalidOperationException(); } return(value); }
uint ReadCount(ReadOnlySpan <byte> json) { uint count; var reader = new JsonReader(new Utf8String(json)); while (reader.Read()) { switch (reader.TokenType) { case JsonReader.JsonTokenType.Property: var name = reader.GetName(); var value = reader.GetValue(); Console.WriteLine("Property {0} = {1}", name, value); if (name == "Count") { if (!PrimitiveParser.TryParse(value, out count)) { return(1); } return(count); } break; } } return(1); }
/// <summary> /// The method based on ReadOnlySpan /// </summary> /// <param name="str"></param> public static void ParseStringSpan(ReadOnlySpan <char> str) { var url = str.Slice(13, 19); var method = str.Slice(58, 3); PrimitiveParser.TryParseInt32(str.Slice(84, 3).AsBytes(), out int statusCode, out int bytesConsumed); var remoteAddr = str.Slice(116, 14); var referrerPolicy = str.Slice(157, 26); var accept = str.Slice(201, 85); var acceptEncoding = str.Slice(313, 13); var acceptLanguage = str.Slice(353, 44); var connection = str.Slice(419, 10); var cookie = str.Slice(447, 118); var host = str.Slice(581, 11); PrimitiveParser.TryParseInt32(str.Slice(629, 1).AsBytes(), out int updgradeInsecureRequest, out int bytesConsumed2); var userAgent = str.Slice(652, 115); Debug.WriteLine(url); Debug.WriteLine(method); Debug.WriteLine(statusCode); Debug.WriteLine(remoteAddr); Debug.WriteLine(accept); Debug.WriteLine(acceptEncoding); Debug.WriteLine(acceptLanguage); Debug.WriteLine(connection); Debug.WriteLine(cookie); Debug.WriteLine(host); Debug.WriteLine(updgradeInsecureRequest); Debug.WriteLine(userAgent); }
// TODO: format should be ReadOnlySpan<T> public static Format.Parsed Parse(ReadOnlySpan <char> format) { if (format.Length == 0) { return(default(Format.Parsed)); } uint precision = NoPrecision; if (format.Length > 1) { var span = format.Slice(1, format.Length - 1); if (!PrimitiveParser.TryParseUInt32(span, out precision)) { throw new NotImplementedException("UnableToParsePrecision"); } if (precision > Parsed.MaxPrecision) { // TODO: this is a contract violation throw new Exception("PrecisionValueOutOfRange"); } } // TODO: this is duplicated from above. It needs to be refactored var specifier = format[0]; return(new Parsed(specifier, (byte)precision)); }
// TODO: how to we chose the lengths of the temp buffers? // TODO: these methods call the slow overloads of PrimitiveParser.TryParseXXX. Do we need fast path? // TODO: these methods hardcode the format. Do we need this to be something that can be specified? public bool TryParseBoolean(out bool value) { int consumed; var unread = Unread; if (PrimitiveParser.TryParseBoolean(unread, out value, out consumed, _encoder)) { if (unread.Length > consumed) { _currentSegmentIndex += consumed; return(true); } } unsafe { byte *temp = stackalloc byte[15]; var tempSpan = new Span <byte>(temp, 15); var copied = CopyTo(tempSpan); if (PrimitiveParser.TryParseBoolean(tempSpan.Slice(0, copied), out value, out consumed, _encoder)) { Advance(consumed); return(true); } } return(false); }
/// <summary> /// Parses a <see cref="ulong"/> from the specified <see cref="ReadableBuffer"/> /// </summary> /// <param name="buffer">The <see cref="ReadableBuffer"/> to parse</param> public unsafe static ulong GetUInt64(this ReadableBuffer buffer) { byte *addr; ulong value; int consumed, len = buffer.Length; if (buffer.IsSingleSpan) { // It fits! addr = (byte *)buffer.First.UnsafePointer; } else if (len < 128) // REVIEW: What's a good number { var data = stackalloc byte[len]; buffer.CopyTo(new Span <byte>(data, len)); addr = data; // memory allocated via stackalloc is valid and // intact until the end of the method; we don't need to worry about scope } else { // Heap allocated copy to parse into array (should be rare) var arr = buffer.ToArray(); if (!PrimitiveParser.TryParse(arr, 0, EncodingData.InvariantUtf8, Format.Parsed.HexUppercase, out value, out consumed)) { throw new InvalidOperationException(); } return(value); } if (!PrimitiveParser.TryParse(addr, 0, len, EncodingData.InvariantUtf8, Format.Parsed.HexUppercase, out value, out consumed)) { throw new InvalidOperationException(); } return(value); }
// once we have a non allocating conversion from string to ReadOnlySpan<char>, we can remove this overload public static Format.Parsed Parse(string format) { if (format == null || format.Length == 0) { return(default(Format.Parsed)); } uint precision = NoPrecision; if (format.Length > 1) { if (!PrimitiveParser.TryParseUInt32(format, 1, format.Length - 1, out precision)) { throw new NotImplementedException("Unable to parse precision specification"); } if (precision > Parsed.MaxPrecision) { // TODO: this is a contract violation throw new Exception("PrecisionValueOutOfRange"); } } var specifier = format[0]; return(new Parsed(specifier, (byte)precision)); }
public static IParserAlphabet Minimal(bool areRegexControlCharactersValid = true) { var parserAlphabet = new ParserAlphabet(); var primitiveParser = new PrimitiveParser(parserAlphabet); parserAlphabet.AddRegexControlCharacters(primitiveParser, areRegexControlCharactersValid); return(parserAlphabet); }
public void TryParseCharacter_ReturnsSuccessResult_WhenStringContainsValidCharacters(string input) { var stream = GetStringStreamFor(input); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseCharacter(stream); Assert.IsTrue(result.IsSuccess); Assert.AreEqual("U", result.Value); }
public void TryParseCharacter_ReturnsFailureResult_WhenStringIsEmpty() { var stream = GetStringStreamFor(""); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseCharacter(stream); Assert.IsFalse(result.IsSuccess); stream.Received(0).Pop(); }
public void TryParseCharacter_ReturnsFailureResult_WhenStringContainsOnlyEscapeCharacter() { var stream = GetStringStreamFor(SpecialCharacters.Escape); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseCharacter(stream); Assert.IsFalse(result.IsSuccess); stream.Received(0).Pop(); }
public void TryParseIntegerInterval_FailureResult_WhenInputStringIsNoValidInterval(string input) { var inputStream = GetStringStreamFor(input); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseIntegerInterval(inputStream); Assert.IsFalse(result.IsSuccess); inputStream.Received(0).Pop(); }
public unsafe void ParseSubstringToUInt32(string text, int index, int count, uint expectedValue, int expectedConsumed) { uint parsedValue; int charsConsumed; bool result = PrimitiveParser.TryParse(text, index, count, out parsedValue, out charsConsumed); Assert.True(result); Assert.Equal(expectedValue, parsedValue); Assert.Equal(expectedConsumed, charsConsumed); }
public void TryParseInteger_ReturnsSuccessResult_WhenStringStartsWithInteger(string input, int expected) { var stream = GetStringStreamFor(input); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseInteger(stream); Assert.IsTrue(result.IsSuccess); Assert.AreEqual(expected, result.Value); }
/// <summary> /// Parses a <see cref="ulong"/> from the specified <see cref="ReadableBuffer"/> /// </summary> /// <param name="buffer">The <see cref="ReadableBuffer"/> to parse</param> public unsafe static ulong GetUInt64(this ReadableBuffer buffer) { byte *addr; ulong value; int consumed, len = buffer.Length; if (buffer.IsSingleSpan) { // It fits! void *pointer; ArraySegment <byte> data; if (buffer.First.TryGetPointer(out pointer)) { if (!PrimitiveParser.TryParseUInt64((byte *)pointer, 0, len, EncodingData.InvariantUtf8, Format.Parsed.HexUppercase, out value, out consumed)) { throw new InvalidOperationException(); } } else if (buffer.First.TryGetArray(out data)) { if (!PrimitiveParser.TryParseUInt64(data.Array, 0, EncodingData.InvariantUtf8, Format.Parsed.HexUppercase, out value, out consumed)) { throw new InvalidOperationException(); } } else { throw new InvalidOperationException(); } } else if (len < 128) // REVIEW: What's a good number { var data = stackalloc byte[len]; buffer.CopyTo(new Span <byte>(data, len)); addr = data; if (!PrimitiveParser.TryParseUInt64(addr, 0, len, EncodingData.InvariantUtf8, Format.Parsed.HexUppercase, out value, out consumed)) { throw new InvalidOperationException(); } } else { // Heap allocated copy to parse into array (should be rare) var arr = buffer.ToArray(); if (!PrimitiveParser.TryParseUInt64(arr, 0, EncodingData.InvariantUtf8, Format.Parsed.HexUppercase, out value, out consumed)) { throw new InvalidOperationException(); } return(value); } return(value); }
public void TryParseCharacter_ReturnsFailureResult_WhenStringConsistsOfEscapeCharacterAndInvalidCharacter() { _alphabet.IsValid(Arg.Any <string>()).Returns(x => !x[0].Equals("N")); var stream = GetStringStreamFor($"{SpecialCharacters.Escape}N"); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseCharacter(stream); Assert.IsFalse(result.IsSuccess); stream.Received(0).Pop(); }
public unsafe void ParseSpanOfCharToUInt32(string text, uint expectedValue, int expectedConsumed) { var span = new ReadOnlySpan <char>(text.ToCharArray()); uint parsedValue; int charsConsumed; bool result = PrimitiveParser.TryParse(span, out parsedValue, out charsConsumed); Assert.True(result); Assert.Equal(expectedValue, parsedValue); Assert.Equal(expectedConsumed, charsConsumed); }
public void TryParseInteger_ReturnsFailureResult_WhenInputStreamIsFaulty(string inputString) { var stream = GetStringStreamFor(inputString); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseInteger(stream); Assert.IsFalse(result.IsSuccess); Assert.AreEqual(RegSeedErrorType.IntegerExpected, result.ErrorType); stream.Received(0).Pop(); }
public void TryParseCharacterRange_ReturnsFailureResult_WhenInputStreamIsTooShortForCharacterRange(string input) { var stream = GetStringStreamFor(input); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseCharacterRange(stream); Assert.IsFalse(result.IsSuccess); Assert.AreEqual(RegSeedErrorType.None, result.ErrorType); stream.Received(0).Pop(); }
public static IParserAlphabet MinimalExtendedBy(IEnumerable <string> additionalValidCharacters, bool areRegexControlCharactersValid = true) { var minimalAlphabet = Minimal(areRegexControlCharactersValid); var primitiveParser = new PrimitiveParser(minimalAlphabet); foreach (var additionalLetter in additionalValidCharacters) { minimalAlphabet.Add(additionalLetter, new CharacterParser(primitiveParser)); } return(minimalAlphabet); }
public void TryParseIntegerInterval_SuccessResult_WhenInputStringIsValidInterval(string input, int?expectedLower, int?expectedUpper, int expectedPopCalls) { var inputStream = GetStringStreamFor(input); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseIntegerInterval(inputStream); Assert.IsTrue(result.IsSuccess); Assert.AreEqual(expectedLower, result.Value.Start); Assert.AreEqual(expectedUpper, result.Value.End); inputStream.Received(expectedPopCalls).Pop(); }
public void TryParseCharacter_ReturnsSuccessResult_WhenStringStartsWithEscapeAndContainsOnlyValidCharacters( string input, string expected) { var stream = GetStringStreamFor(input); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseCharacter(stream); Assert.IsTrue(result.IsSuccess); Assert.AreEqual(expected, result.Value); stream.Received(2).Pop(); }
public void ConstructorWithPattern_GenerateCreatesString_WhenCalledWithParserAlphabet() { var alphabet = RegexAlphabetFactory.Minimal(); var primitiveParser = new PrimitiveParser(alphabet); alphabet.Add("a", new CharacterParser(primitiveParser)); var regseed = new RegSeed("a", new Random(), alphabet); var result = regseed.Generate(); Assert.AreEqual("a", result); }
public unsafe void ParseUtf8StringToUInt32(string text, uint expectedValue, int expectedConsumed) { var utf8 = new Utf8String(text); uint parsedValue; int bytesConsumed; bool result = PrimitiveParser.TryParse(utf8, out parsedValue, out bytesConsumed); Assert.True(result); Assert.Equal(expectedValue, parsedValue); Assert.Equal(expectedConsumed, bytesConsumed); }
public void TryParseCharacterRange_ReturnsFailureResult_WhenThirdCharacterIsInvalidCharacter(string inputStream) { _alphabet.IsValid(Arg.Any <string>()).Returns(x => !x[0].Equals("s")); var stream = GetStringStreamFor(inputStream); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseCharacterRange(stream); Assert.IsFalse(result.IsSuccess); Assert.AreEqual(RegSeedErrorType.CharacterRangeExpected, result.ErrorType); _alphabet.Received(2).IsValid(Arg.Any <string>()); stream.Received(0).Pop(); }
public void TryParseCharacterRange_ReturnsFailureResult_WhenFirstStreamCharacterIsNotValidCharacter() { _alphabet.IsValid(Arg.Any <string>()).Returns(false); var stream = GetStringStreamFor("n-2"); var parser = new PrimitiveParser(_alphabet); var result = parser.TryParseCharacterRange(stream); Assert.IsFalse(result.IsSuccess); Assert.AreEqual(RegSeedErrorType.None, result.ErrorType); _alphabet.Received(1).IsValid(Arg.Any <string>()); stream.Received(0).Pop(); }
public unsafe void ParseUtf8SpanOfBytesToUInt32(string text, uint expectedValue, int expectedConsumed) { byte[] textBuffer = Encoding.UTF8.GetBytes(text); var span = new ReadOnlySpan <byte>(textBuffer); uint parsedValue; int bytesConsumed; bool result = PrimitiveParser.TryParse(span, EncodingData.Encoding.Utf8, out parsedValue, out bytesConsumed); Assert.True(result); Assert.Equal(expectedValue, parsedValue); Assert.Equal(expectedConsumed, bytesConsumed); }