public static Result Parse(ReadOnlySpan <char> span, out Single value) { int ich = 0; for (; ; ich++) { if (ich >= span.Length) { value = 0; return(Result.Empty); } if (!char.IsWhiteSpace(span[ich])) { break; } } // Handle the common case of a single digit or ? if (span.Length - ich == 1) { char ch = span[ich]; if (ch >= '0' && ch <= '9') { value = ch - '0'; return(Result.Good); } if (ch == '?') { value = Single.NaN; return(Result.Good); } } int ichEnd; if (!DoubleParser.TryParse(span.Slice(ich, span.Length - ich), out value, out ichEnd)) { value = default(Single); return(Result.Error); } // Make sure everything was consumed. while (ichEnd < span.Length) { if (!char.IsWhiteSpace(span[ichEnd])) { return(Result.Extra); } ichEnd++; } return(Result.Good); }
public static (bool isSuccess, string key, float[] values) ParseKeyThenNumbers(string line, bool invariantCulture) { if (string.IsNullOrWhiteSpace(line)) { return(false, null, null); } ReadOnlySpan <char> trimmedLine = line.AsSpan().TrimEnd(); // TrimEnd creates a Span, no allocations int firstSeparatorIndex = trimmedLine.IndexOfAny(' ', '\t'); // the first word is the key, we just skip it ReadOnlySpan <char> valuesToParse = trimmedLine.Slice(start: firstSeparatorIndex + 1); float[] values = AllocateFixedSizeArrayToStoreParsedValues(valuesToParse); int toParseStartIndex = 0; int valueIndex = 0; for (int i = 0; i <= valuesToParse.Length; i++) { if (i == valuesToParse.Length || valuesToParse[i] == ' ' || valuesToParse[i] == '\t') { if (invariantCulture) { if (DoubleParser.TryParse(valuesToParse.Slice(toParseStartIndex, i - toParseStartIndex), out float parsed)) { values[valueIndex++] = parsed; } else { return(false, null, null); } } else { if (float.TryParse(valuesToParse.Slice(toParseStartIndex, i - toParseStartIndex).ToString(), out float parsed)) { values[valueIndex++] = parsed; } else { return(false, null, null); } } toParseStartIndex = i + 1; } } return(true, trimmedLine.Slice(0, firstSeparatorIndex).ToString(), values); }