public static Result Parse(out Single value, string s, int ichMin, int ichLim) { Contracts.Assert(0 <= ichMin && ichMin <= ichLim && ichLim <= Utils.Size(s)); for (; ; ichMin++) { if (ichMin >= ichLim) { value = 0; return(Result.Empty); } if (!char.IsWhiteSpace(s[ichMin])) { break; } } // Handle the common case of a single digit or ? if (ichLim - ichMin == 1) { char ch = s[ichMin]; if (ch >= '0' && ch <= '9') { value = ch - '0'; return(Result.Good); } if (ch == '?') { value = Single.NaN; return(Result.Good); } } int ichEnd; if (!DoubleParser.TryParse(out value, s, ichMin, ichLim, out ichEnd)) { value = default(Single); return(Result.Error); } // Make sure everything was consumed. while (ichEnd < ichLim) { if (!char.IsWhiteSpace(s[ichEnd])) { return(Result.Extra); } ichEnd++; } return(Result.Good); }
public static (bool isSuccess, string key, float[] values) ParseKeyThenNumbers(string line) { 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 (DoubleParser.TryParse(valuesToParse.Slice(toParseStartIndex, i - toParseStartIndex), out float parsed)) { values[valueIndex++] = parsed; } else { return(false, null, null); } toParseStartIndex = i + 1; } } return(true, trimmedLine.Slice(0, firstSeparatorIndex).ToString(), values); }