public static bool TryParseByte(ReadOnlySpan <byte> text, out byte value, out int bytesConsumed, ParsedFormat format = default, SymbolTable symbolTable = null) { symbolTable = symbolTable ?? SymbolTable.InvariantUtf8; if (!format.IsDefault && format.HasPrecision) { throw new NotImplementedException("Format with precision not supported."); } if (symbolTable == SymbolTable.InvariantUtf8) { if (Parsers.IsHexFormat(format)) { return(Utf8Parser.Hex.TryParseByte(text, out value, out bytesConsumed)); } else { return(Utf8Parser.TryParseByte(text, out value, out bytesConsumed)); } } else if (symbolTable == SymbolTable.InvariantUtf16) { ReadOnlySpan <char> utf16Text = text.NonPortableCast <byte, char>(); int charactersConsumed; bool result; if (Parsers.IsHexFormat(format)) { result = Utf16Parser.Hex.TryParseByte(utf16Text, out value, out charactersConsumed); } else { result = Utf16Parser.TryParseByte(utf16Text, out value, out charactersConsumed); } bytesConsumed = charactersConsumed * sizeof(char); return(result); } if (Parsers.IsHexFormat(format)) { throw new NotImplementedException("The only supported encodings for hexadecimal parsing are InvariantUtf8 and InvariantUtf16."); } if (!(format.IsDefault || format.Symbol == 'G' || format.Symbol == 'g')) { throw new NotImplementedException(String.Format("Format '{0}' not supported.", format.Symbol)); } SymbolTable.Symbol nextSymbol; int thisSymbolConsumed; if (!symbolTable.TryParse(text, out nextSymbol, out thisSymbolConsumed)) { value = default; bytesConsumed = 0; return(false); } if (nextSymbol > SymbolTable.Symbol.D9) { value = default; bytesConsumed = 0; return(false); } uint parsedValue = (uint)nextSymbol; int index = thisSymbolConsumed; while (index < text.Length) { bool success = symbolTable.TryParse(text.Slice(index), out nextSymbol, out thisSymbolConsumed); if (!success || nextSymbol > SymbolTable.Symbol.D9) { bytesConsumed = index; value = (byte)parsedValue; return(true); } // If parsedValue > (byte.MaxValue / 10), any more appended digits will cause overflow. // if parsedValue == (byte.MaxValue / 10), any nextDigit greater than 5 implies overflow. if (parsedValue > byte.MaxValue / 10 || (parsedValue == byte.MaxValue / 10 && nextSymbol > SymbolTable.Symbol.D5)) { bytesConsumed = 0; value = default; return(false); } index += thisSymbolConsumed; parsedValue = parsedValue * 10 + (uint)nextSymbol; } bytesConsumed = text.Length; value = (byte)parsedValue; return(true); }
private static bool TryFormatNumber(double value, bool isSingle, Span <byte> buffer, out int bytesWritten, StandardFormat format = default, SymbolTable symbolTable = null) { Precondition.Require(format.Symbol == 'G' || format.Symbol == 'E' || format.Symbol == 'F'); symbolTable = symbolTable ?? SymbolTable.InvariantUtf8; bytesWritten = 0; int written; if (Double.IsNaN(value)) { return(symbolTable.TryEncode(SymbolTable.Symbol.NaN, buffer, out bytesWritten)); } if (Double.IsInfinity(value)) { if (Double.IsNegativeInfinity(value)) { if (!symbolTable.TryEncode(SymbolTable.Symbol.MinusSign, buffer, out written)) { bytesWritten = 0; return(false); } bytesWritten += written; } if (!symbolTable.TryEncode(SymbolTable.Symbol.InfinitySign, buffer.Slice(bytesWritten), out written)) { bytesWritten = 0; return(false); } bytesWritten += written; return(true); } // TODO: the lines below need to be replaced with properly implemented algorithm // the problem is the algorithm is complex, so I am commiting a stub for now var hack = value.ToString(format.Symbol.ToString()); var utf16Bytes = MemoryMarshal.AsBytes(hack.AsSpan()); if (symbolTable == SymbolTable.InvariantUtf8) { var status = Encodings.Utf16.ToUtf8(utf16Bytes, buffer, out int consumed, out bytesWritten); return(status == OperationStatus.Done); } else if (symbolTable == SymbolTable.InvariantUtf16) { bytesWritten = utf16Bytes.Length; if (utf16Bytes.TryCopyTo(buffer)) { return(true); } bytesWritten = 0; return(false); } else { // TODO: This is currently pretty expensive. Can this be done more efficiently? // Note: removing the hack might solve this problem a very different way. var status = Encodings.Utf16.ToUtf8Length(utf16Bytes, out int needed); if (status != OperationStatus.Done) { bytesWritten = 0; return(false); } Span <byte> temp = stackalloc byte[needed]; status = Encodings.Utf16.ToUtf8(utf16Bytes, temp, out int consumed, out written); if (status != OperationStatus.Done) { bytesWritten = 0; return(false); } return(symbolTable.TryEncode(temp, buffer, out consumed, out bytesWritten)); } }