public static bool TryFormat(this DateTimeOffset value, Span <byte> buffer, out int bytesWritten, ParsedFormat format = default, SymbolTable symbolTable = null) => Formatters.Custom.TryFormat(value, buffer, out bytesWritten, format, symbolTable);
public bool TryFormat(Span <byte> buffer, out int written, ParsedFormat format, SymbolTable symbolTable) { return(_name.TryFormatQuotedString(buffer, out written, format, symbolTable)); }
public static bool TryAppend <TFormatter>(this TFormatter formatter, double value, SymbolTable symbolTable, ParsedFormat format = default) where TFormatter : IOutput { int bytesWritten; if (!value.TryFormat(formatter.Buffer, out bytesWritten, format, symbolTable)) { return(false); } formatter.Advance(bytesWritten); return(true); }
static void AppendUntyped <TFormatter, T>(this TFormatter formatter, T value, ParsedFormat format) where TFormatter : ITextOutput { #region Built in types var i32 = value as int?; if (i32 != null) { formatter.Append(i32.Value, format); return; } var i64 = value as long?; if (i64 != null) { formatter.Append(i64.Value, format); return; } var i16 = value as short?; if (i16 != null) { formatter.Append(i16.Value, format); return; } var b = value as byte?; if (b != null) { formatter.Append(b.Value, format); return; } var c = value as char?; if (c != null) { formatter.Append(c.Value); return; } var u32 = value as uint?; if (u32 != null) { formatter.Append(u32.Value, format); return; } var u64 = value as ulong?; if (u64 != null) { formatter.Append(u64.Value, format); return; } var u16 = value as ushort?; if (u16 != null) { formatter.Append(u16.Value, format); return; } var sb = value as sbyte?; if (sb != null) { formatter.Append(sb.Value, format); return; } var str = value as string; if (str != null) { formatter.Append(str); return; } var dt = value as DateTime?; if (dt != null) { formatter.Append(dt.Value, format); return; } var dto = value as DateTimeOffset?; if (dto != null) { formatter.Append(dto.Value, format); return; } var ts = value as TimeSpan?; if (ts != null) { formatter.Append(ts.Value, format); return; } var guid = value as Guid?; if (guid != null) { formatter.Append(guid.Value, format); return; } #endregion if (value is IBufferFormattable) { formatter.Append((IBufferFormattable)value, format); // this is boxing. not sure how to avoid it. return; } throw new NotSupportedException("value is not formattable."); }
private static void Verify(ParsedFormat format, byte expectedPrecision, char expectedSymbol) { Assert.Equal(format.Precision, expectedPrecision); Assert.Equal(format.Symbol, expectedSymbol.ToString()[0]); }
private static bool TryFormatNumber(double value, bool isSingle, Span<byte> buffer, out int bytesWritten, ParsedFormat 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 = hack.AsReadOnlySpan().AsBytes(); if (symbolTable == SymbolTable.InvariantUtf8) { var status = Encoders.Utf16.ToUtf8(utf16Bytes, buffer, out int consumed, out bytesWritten); return status == Buffers.TransformationStatus.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 = Encoders.Utf16.ToUtf8Length(utf16Bytes, out int needed); if (status != Buffers.TransformationStatus.Done) { bytesWritten = 0; return false; } Span<byte> temp; unsafe { var buf = stackalloc byte[needed]; temp = new Span<byte>(buf, needed); } status = Encoders.Utf16.ToUtf8(utf16Bytes, temp, out int consumed, out written); if (status != Buffers.TransformationStatus.Done) { bytesWritten = 0; return false; } return symbolTable.TryEncode(temp, buffer, out consumed, out bytesWritten); } }
public static bool TryFormat(sbyte value, Span <byte> buffer, out int bytesWritten, ParsedFormat format = default) => TryFormatCore(value, 0xff, buffer, out bytesWritten, format);
public void ParseSimpleFormats() { ParsedFormat parsed; parsed = ParsedFormat.Parse("B"); Verify(parsed, ParsedFormat.NoPrecision, 'B'); parsed = ParsedFormat.Parse("b"); Verify(parsed, ParsedFormat.NoPrecision, 'b'); parsed = ParsedFormat.Parse("D"); Verify(parsed, ParsedFormat.NoPrecision, 'D'); parsed = ParsedFormat.Parse("d"); Verify(parsed, ParsedFormat.NoPrecision, 'd'); parsed = ParsedFormat.Parse("E"); Verify(parsed, ParsedFormat.NoPrecision, 'E'); parsed = ParsedFormat.Parse("e"); Verify(parsed, ParsedFormat.NoPrecision, 'e'); parsed = ParsedFormat.Parse("F"); Verify(parsed, ParsedFormat.NoPrecision, 'F'); parsed = ParsedFormat.Parse("f"); Verify(parsed, ParsedFormat.NoPrecision, 'f'); parsed = ParsedFormat.Parse("G"); Verify(parsed, ParsedFormat.NoPrecision, 'G'); parsed = ParsedFormat.Parse("g"); Verify(parsed, ParsedFormat.NoPrecision, 'g'); parsed = ParsedFormat.Parse("N"); Verify(parsed, ParsedFormat.NoPrecision, 'N'); parsed = ParsedFormat.Parse("n"); Verify(parsed, ParsedFormat.NoPrecision, 'n'); parsed = ParsedFormat.Parse("O"); Verify(parsed, ParsedFormat.NoPrecision, 'O'); parsed = ParsedFormat.Parse("o"); Verify(parsed, ParsedFormat.NoPrecision, 'o'); parsed = ParsedFormat.Parse("P"); Verify(parsed, ParsedFormat.NoPrecision, 'P'); parsed = ParsedFormat.Parse("p"); Verify(parsed, ParsedFormat.NoPrecision, 'p'); parsed = ParsedFormat.Parse("R"); Verify(parsed, ParsedFormat.NoPrecision, 'R'); parsed = ParsedFormat.Parse("r"); Verify(parsed, ParsedFormat.NoPrecision, 'r'); parsed = ParsedFormat.Parse("t"); Verify(parsed, ParsedFormat.NoPrecision, 't'); parsed = ParsedFormat.Parse("X"); Verify(parsed, ParsedFormat.NoPrecision, 'X'); parsed = ParsedFormat.Parse("x"); Verify(parsed, ParsedFormat.NoPrecision, 'x'); }
public static bool TryFormat(DateTime value, Span <byte> buffer, out int bytesWritten, ParsedFormat format = default) { char symbol = format.IsDefault ? 'G' : format.Symbol; switch (symbol) { case 'R': return(TryFormatRfc1123(value, buffer, out bytesWritten)); case 'l': return(TryFormatRfc1123Lowercase(value, buffer, out bytesWritten)); case 'O': return(TryFormatO(value, NullOffset, buffer, out bytesWritten)); case 'G': return(TryFormatG(value, NullOffset, buffer, out bytesWritten)); default: throw new NotSupportedException(); } }
public static bool TryFormat(TimeSpan value, Span <byte> buffer, out int bytesWritten, ParsedFormat format = default) { char symbol = format.IsDefault ? 'c' : format.Symbol; switch (symbol) { case 'G': case 'g': case 'c': case 't': case 'T': return(TryFormatTimeSpan(value, symbol, buffer, out bytesWritten)); default: throw new NotSupportedException(); } }
public static bool TryFormat(DateTimeOffset value, Span <byte> buffer, out int bytesWritten, ParsedFormat format = default) { TimeSpan offset = NullOffset; char symbol = format.Symbol; if (format.IsDefault) { symbol = 'G'; offset = value.Offset; } switch (symbol) { case 'R': return(TryFormatRfc1123(value.UtcDateTime, buffer, out bytesWritten)); case 'l': return(TryFormatRfc1123Lowercase(value.UtcDateTime, buffer, out bytesWritten)); case 'O': return(TryFormatO(value.DateTime, value.Offset, buffer, out bytesWritten)); case 'G': return(TryFormatG(value.DateTime, offset, buffer, out bytesWritten)); default: throw new NotSupportedException(); } }
public static bool TryFormat(this float value, Span <byte> buffer, out int bytesWritten, ParsedFormat format = default) => Custom.TryFormat(value, buffer, out bytesWritten, format, SymbolTable.InvariantUtf8);
static bool TryFormatCore(ulong value, Span <byte> buffer, out int bytesWritten, ParsedFormat format) { if (format.IsDefault) { format = 'G'; } switch (format.Symbol) { case 'd': case 'D': case 'G': case 'g': return(TryFormatDecimalUInt64(value, format.Precision, buffer, out bytesWritten)); case 'n': case 'N': return(TryFormatNumericUInt64(value, format.Precision, buffer, out bytesWritten)); case 'x': return(TryFormatHexUInt64(value, format.Precision, true, buffer, out bytesWritten)); case 'X': return(TryFormatHexUInt64(value, format.Precision, false, buffer, out bytesWritten)); default: throw new NotSupportedException(); } }
// TODO: this should be properly implemented // currently it handles formatting to UTF8 only. public static bool TryFormat(this Utf8String str, Span <byte> buffer, out int written, ParsedFormat format, SymbolTable symbolTable) { written = 0; if (buffer.Length < str.Length) { return(false); } foreach (var cp in str) { var b = cp; buffer[written++] = cp; } return(true); }
public static void Append <TFormatter>(this TFormatter formatter, short value, ParsedFormat format = default) where TFormatter : ITextOutput { while (!formatter.TryAppend(value, format)) { formatter.Enlarge(); } }
public static bool TryFormatQuotedString(this Utf8String str, Span <byte> buffer, out int written, ParsedFormat format, SymbolTable symbolTable) { written = 0; int justWritten; unsafe { if (!symbolTable.TryEncode((byte)'"', buffer, out justWritten)) { return(false); } written += justWritten; if (!str.TryFormat(buffer.Slice(written), out justWritten, format, symbolTable)) { return(false); } written += justWritten; if (!symbolTable.TryEncode((byte)'"', buffer.Slice(written), out justWritten)) { return(false); } } written += justWritten; return(true); }
public static bool TryFormat(this TimeSpan value, Span <byte> buffer, out int bytesWritten, ParsedFormat format = default, SymbolTable symbolTable = null) => CustomFormatter.TryFormat(value, buffer, out bytesWritten, format, symbolTable);
public void ParseThrowsExceptionWhenParsedPrecisionExceedsMaxPrecision() { var ex = Assert.Throws<FormatException>(() => ParsedFormat.Parse($"x{100}")); }
public static void Append <TFormatter>(this TFormatter formatter, double value, SymbolTable symbolTable, ParsedFormat format = default) where TFormatter : IOutput { while (!formatter.TryAppend(value, symbolTable, format)) { formatter.Enlarge(); } }
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 (IsHexFormat(format)) { return(InvariantUtf8.Hex.TryParseByte(text, out value, out bytesConsumed)); } else { return(InvariantUtf8.TryParseByte(text, out value, out bytesConsumed)); } } else if (symbolTable == SymbolTable.InvariantUtf16) { ReadOnlySpan <char> utf16Text = text.NonPortableCast <byte, char>(); int charsConsumed; bool result; if (IsHexFormat(format)) { result = InvariantUtf16.Hex.TryParseByte(utf16Text, out value, out charsConsumed); } else { result = InvariantUtf16.TryParseByte(utf16Text, out value, out charsConsumed); } bytesConsumed = charsConsumed * sizeof(char); return(result); } if (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); }
public static unsafe bool TryFormat(Guid value, Span <byte> buffer, out int bytesWritten, ParsedFormat format = default) { bool dash = format.Symbol != 'N'; bool bookEnds = (format.Symbol == 'B') || (format.Symbol == 'P'); bytesWritten = (GuidChars + (dash ? 4 : 0) + (bookEnds ? 2 : 0)) * sizeof(char); if (buffer.Length < bytesWritten) { bytesWritten = 0; return(false); } Span <char> dst = buffer.NonPortableCast <byte, char>(); ref char utf16Bytes = ref dst.DangerousGetPinnableReference();