private static TagParserResult ParseTag(string tag, bool throwException) { var result = new TagParserResult(); using (var buffer = MemoryPool <char> .Shared.Rent(tag.Length)) { var input = buffer.Memory.Slice(0, tag.Length).Span; tag.AsSpan().ToLowerInvariant(input); var indexStart = 0; var state = TagParserState.Area; ReadOnlySpan <char> type = null; for (var i = 0; i < input.Length; i++) { if (input[i] != '.' && input[i] != ',') { continue; } Parse(tag, ref result, ref indexStart, ref state, ref type, input.Slice(indexStart, i - indexStart), i, throwException); } Parse(tag, ref result, ref indexStart, ref state, ref type, input.Slice(indexStart), input.Length - 1, throwException); state = TagParserState.TypeValidation; Parse(tag, ref result, ref indexStart, ref state, ref type, input, input.Length - 1, throwException); if (state == TagParserState.Success) { result.ErrorState = TagParserState.Success; } } return(result); }
private static void Parse(string tag, ref TagParserResult result, ref int indexStart, ref TagParserState state, ref ReadOnlySpan <char> type, ReadOnlySpan <char> data, int index, bool throwException = false) { if (!TryExtractData(ref result, data, ref indexStart, ref state, ref type, index) && throwException) { result.ErrorState = state; ThrowHelper.ThrowTagParseException(TagParserState.Area, data.ToString(), tag); } }
// DB1.80000,x,1 public static bool TryParseTag(string tag, out TagParserResult result) { result = ParseTag(tag, false); return(result.ErrorState == TagParserState.Success); }
private static bool TryExtractData(ref TagParserResult result, ReadOnlySpan <char> input, ref int indexStart, ref TagParserState state, ref ReadOnlySpan <char> type, int i) { switch (state) { case TagParserState.Area: { if (TryDetectArea(input, out var selector, out var db)) { result.Area = selector; result.DbNumber = db; indexStart = i + 1; state = TagParserState.Offset; return(true); } } break; case TagParserState.Offset: { // TODO: !!!!!!! #if SPANSUPPORT if (int.TryParse(input, out var offset)) #else if (TryConvertSpanToInt32(input, out var offset)) #endif { result.Offset = offset; indexStart = i + 1; state = TagParserState.Type; return(true); } } break; case TagParserState.Type: { type = input; state = TagParserState.NumberOfItems; indexStart = i + 1; return(true); } case TagParserState.NumberOfItems: { if (input.IsEmpty) { return(true); } // TODO: !!!!!!! #if SPANSUPPORT if (ushort.TryParse(input, out var length)) #else if (TryConvertSpanToUShort(input, out var length)) #endif { result.Length = length; state = TagParserState.TypeValidation; return(true); } } break; case TagParserState.TypeValidation: { if (result.Length <= 0) { result.Length = 1; } var offset = result.Offset; var length = result.Length; if (!type.IsEmpty && TryDetectTypes(type, ref length, ref offset, out var vtype, out var rType, out var unicode)) { result.Length = length; result.Offset = offset; result.VarType = vtype; result.ResultType = rType; result.Encoding = unicode; indexStart = i + 1; state = TagParserState.Success; return(true); } } break; case TagParserState.Success: return(true); } return(false); }