Example #1
0
 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);
Example #2
0
 public bool TryFormat(Span <byte> buffer, out int written, ParsedFormat format, SymbolTable symbolTable)
 {
     return(_name.TryFormatQuotedString(buffer, out written, format, symbolTable));
 }
Example #3
0
        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]);
 }
Example #6
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);
            }
        }
Example #7
0
 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');
        }
Example #9
0
        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();
            }
        }
Example #10
0
        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();
            }
        }
Example #11
0
        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();
            }
        }
Example #12
0
 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);
Example #13
0
        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();
            }
        }
Example #14
0
        // 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);
        }
Example #15
0
 public static void Append <TFormatter>(this TFormatter formatter, short value, ParsedFormat format = default) where TFormatter : ITextOutput
 {
     while (!formatter.TryAppend(value, format))
     {
         formatter.Enlarge();
     }
 }
Example #16
0
        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);
        }
Example #17
0
 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}"));
 }
Example #19
0
 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();
     }
 }
Example #20
0
        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);
        }
Example #21
0
        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();