public static bool TryFormat(this DateTime value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if (format.IsDefault) { format.Symbol = 'G'; } Precondition.Require(format.Symbol == 'R' || format.Symbol == 'O' || format.Symbol == 'G'); switch (format.Symbol) { case 'R': var utc = value.ToUniversalTime(); if (formattingData.IsUtf16) { return TryFormatDateTimeRfc1123(utc, buffer, FormattingData.InvariantUtf16, out bytesWritten); } else { return TryFormatDateTimeRfc1123(utc, buffer, FormattingData.InvariantUtf8, out bytesWritten); } case 'O': if (formattingData.IsUtf16) { return TryFormatDateTimeFormatO(value, true, buffer, FormattingData.InvariantUtf16, out bytesWritten); } else { return TryFormatDateTimeFormatO(value, true, buffer, FormattingData.InvariantUtf8, out bytesWritten); } case 'G': return TryFormatDateTimeFormagG(value, buffer, formattingData, out bytesWritten); default: throw new NotImplementedException(); } }
internal static bool TryFormatUInt64(ulong value, byte numberOfBytes, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if(format.Symbol == 'g') { format.Symbol = 'G'; } if (format.IsHexadecimal && formattingData.IsUtf16) { return TryFormatHexadecimalInvariantCultureUtf16(value, buffer, format, out bytesWritten); } if (format.IsHexadecimal && formattingData.IsUtf8) { return TryFormatHexadecimalInvariantCultureUtf8(value, buffer, format, out bytesWritten); } if ((formattingData.IsInvariantUtf16) && (format.Symbol == 'D' || format.Symbol == 'G')) { return TryFormatDecimalInvariantCultureUtf16(value, buffer, format, out bytesWritten); } if ((formattingData.IsInvariantUtf8) && (format.Symbol == 'D' || format.Symbol == 'G')) { return TryFormatDecimalInvariantCultureUtf8(value, buffer, format, out bytesWritten); } return TryFormatDecimal(value, buffer, format, formattingData, out bytesWritten); }
internal static bool TryFormatInt64(long value, byte numberOfBytes, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { Precondition.Require(numberOfBytes <= sizeof(long)); if (value >= 0) { return TryFormatUInt64(unchecked((ulong)value), numberOfBytes, buffer, format, formattingData, out bytesWritten); } else if (format.IsHexadecimal) { ulong bitMask = GetBitMask(numberOfBytes); return TryFormatUInt64(unchecked((ulong)value) & bitMask, numberOfBytes, buffer, format, formattingData, out bytesWritten); } else { int minusSignBytes = 0; if(!formattingData.TryWriteSymbol(FormattingData.Symbol.MinusSign, buffer, out minusSignBytes)) { bytesWritten = 0; return false; } int digitBytes = 0; if(!TryFormatUInt64(unchecked((ulong)-value), numberOfBytes, buffer.Slice(minusSignBytes), format, formattingData, out digitBytes)) { bytesWritten = 0; return false; } bytesWritten = digitBytes + minusSignBytes; return true; } }
public static bool TryFormat(this float value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if (format.IsDefault) { format.Symbol = 'G'; } Precondition.Require(format.Symbol == 'G'); return FloatFormatter.TryFormatNumber(value, true, buffer, format, formattingData, out bytesWritten); }
public bool TryFormat(Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if (!PrimitiveFormatters.TryFormat(_age, buffer, format, formattingData, out bytesWritten)) return false; char symbol = _inMonths ? 'm' : 'y'; int symbolBytes; if (!PrimitiveFormatters.TryFormat(symbol, buffer.Slice(bytesWritten), format, formattingData, out symbolBytes)) return false; bytesWritten += symbolBytes; return true; }
public static bool TryFormat(this char value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if (formattingData.IsUtf16) { if (buffer.Length < 2) { bytesWritten = 0; return false; } buffer[0] = (byte)value; buffer[1] = (byte)(value >> 8); bytesWritten = 2; return true; } if (buffer.Length < 1) { bytesWritten = 0; return false; } // fast path for ASCII if (value <= 127) { buffer[0] = (byte)value; bytesWritten = 1; return true; } // TODO: This can be directly encoded to SpanByte. There is no conversion between spans yet var encoded = new Utf8EncodedCodePoint(value); bytesWritten = encoded.Length; if (buffer.Length < bytesWritten) { bytesWritten = 0; return false; } buffer[0] = encoded.Byte0; if(bytesWritten > 1) { buffer[1] = encoded.Byte1; } if(bytesWritten > 2) { buffer[2] = encoded.Byte2; } if(bytesWritten > 3) { buffer[3] = encoded.Byte3; } return true; }
public static bool TryFormat(this char value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if (formattingData.IsUtf16) { if (buffer.Length < 2) { bytesWritten = 0; return false; } buffer[0] = (byte)value; buffer[1] = (byte)(value >> 8); bytesWritten = 2; return true; } if (buffer.Length < 1) { bytesWritten = 0; return false; } // fast path for ASCII if (value <= 127) { buffer[0] = (byte)value; bytesWritten = 1; return true; } var encoded = new FourBytes(); bytesWritten = Utf8Encoder.CharToUtf8(value, ref encoded); if(buffer.Length < bytesWritten) { bytesWritten = 0; return false; } buffer[0] = encoded.B0; if(bytesWritten > 1) { buffer[1] = encoded.B1; } if(bytesWritten > 2) { buffer[2] = encoded.B2; } if(bytesWritten > 3) { buffer[3] = encoded.B3; } return true; }
private static bool TryFormatDecimalInvariantCultureUtf16(ulong value, Span<byte> buffer, Format.Parsed format, out int bytesWritten) { Precondition.Require(format.Symbol == 'D' || format.Symbol == 'G'); // Count digits var valueToCountDigits = value; var digitsCount = 1; while (valueToCountDigits >= 10UL) { valueToCountDigits = valueToCountDigits / 10UL; digitsCount++; } var index = 0; var bytesCount = digitsCount * 2; // If format is D and precision is greater than digits count, append leading zeros if (format.Symbol == 'D' && format.HasPrecision) { var leadingZerosCount = format.Precision - digitsCount; if (leadingZerosCount > 0) { bytesCount += leadingZerosCount * 2; } if (bytesCount > buffer.Length) { bytesWritten = 0; return false; } while (leadingZerosCount-- > 0) { buffer[index++] = (byte)'0'; buffer[index++] = 0; } } else if (bytesCount > buffer.Length) { bytesWritten = 0; return false; } index = bytesCount; while (digitsCount-- > 0) { ulong digit = value % 10UL; value /= 10UL; buffer[--index] = 0; buffer[--index] = (byte)(digit + (ulong)'0'); } bytesWritten = bytesCount; return true; }
public static bool TryFormatNumber(double value, bool isSingle, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { Precondition.Require(format.Symbol == 'G' || format.Symbol == 'E' || format.Symbol == 'F'); bytesWritten = 0; int written; if (Double.IsNaN(value)) { return formattingData.TryWriteSymbol(FormattingData.Symbol.NaN, buffer, out bytesWritten); } if (Double.IsInfinity(value)) { if (Double.IsNegativeInfinity(value)) { if (!formattingData.TryWriteSymbol(FormattingData.Symbol.MinusSign, buffer, out written)) { bytesWritten = 0; return false; } bytesWritten += written; } if (!formattingData.TryWriteSymbol(FormattingData.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()); return hack.TryFormat(buffer, default(Format.Parsed), formattingData, out bytesWritten); }
private static void Verify(Format.Parsed format, byte expectedPrecision, char expectedSymbol) { Assert.Equal(format.Precision, expectedPrecision); Assert.Equal(format.Symbol, expectedSymbol.ToString()[0]); }
private static bool TryFormatTimeSpanG(TimeSpan value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { bytesWritten = 0; if (value.Ticks < 0) { if (!TryWriteChar('-', buffer, formattingData, ref bytesWritten)) { return false; } } bool daysWritten = false; if (value.Days != 0 || format.Symbol == 'G') { if (!TryWriteInt32(Abs(value.Days), buffer, default(Format.Parsed), formattingData, ref bytesWritten)) { return false; } daysWritten = true; if (format.Symbol == 'c') { if (!TryWriteChar('.', buffer, formattingData, ref bytesWritten)) { return false; } } else { if (!TryWriteChar(':', buffer, formattingData, ref bytesWritten)) { return false; } } } var hourFormat = default(Format.Parsed); if ((daysWritten || format.Symbol == 'c') && format.Symbol != 'g') { hourFormat = D2; } if (!TryWriteInt32(Abs(value.Hours), buffer, hourFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteChar(':', buffer, formattingData, ref bytesWritten)) { return false; } if (!TryWriteInt32(Abs(value.Minutes), buffer, D2, formattingData, ref bytesWritten)) { return false; } if (!TryWriteChar(':', buffer, formattingData, ref bytesWritten)) { return false; } if (!TryWriteInt32(Abs(value.Seconds), buffer, D2, formattingData, ref bytesWritten)) { return false; } long remainingTicks; if (value.Ticks != long.MinValue) { remainingTicks = Abs(value.Ticks) % TimeSpan.TicksPerSecond; } else { remainingTicks = long.MaxValue % TimeSpan.TicksPerSecond; remainingTicks = (remainingTicks + 1) % TimeSpan.TicksPerSecond; } var ticksFormat = D7; if (remainingTicks != 0) { if (!TryWriteChar('.', buffer, formattingData, ref bytesWritten)) { return false; } var fraction = remainingTicks * FractionalTimeScale / TimeSpan.TicksPerSecond; if (!TryWriteInt64(fraction, buffer, ticksFormat, formattingData, ref bytesWritten)) { return false; } } return true; }
public static bool TryFormat(this DateTime value, Span <byte> buffer, ReadOnlySpan <char> format, FormattingData formattingData, out int bytesWritten) { Format.Parsed parsedFormat = Format.Parse(format); return(TryFormat(value, buffer, parsedFormat, formattingData, out bytesWritten)); }
public static bool TryFormat(this Guid value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if (format.IsDefault) { format.Symbol = 'G'; } Precondition.Require(format.Symbol == 'G' || format.Symbol == 'D' || format.Symbol == 'N' || format.Symbol == 'B' || format.Symbol == 'P'); bool dash = true; char tail = '\0'; bytesWritten = 0; switch (format.Symbol) { case 'D': case 'G': break; case 'N': dash = false; break; case 'B': if (!TryWriteChar('{', buffer, formattingData, ref bytesWritten)) { return false; } tail = '}'; break; case 'P': if (!TryWriteChar('(', buffer, formattingData, ref bytesWritten)) { return false; } tail = ')'; break; default: Precondition.Require(false); // how did we get here? break; } var byteFormat = new Format.Parsed('x', 2); unsafe { byte* bytes = (byte*)&value; if (!TryWriteByte(bytes[3], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteByte(bytes[2], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteByte(bytes[1], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteByte(bytes[0], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (dash) { if (!TryWriteChar('-', buffer, formattingData, ref bytesWritten)) { return false; } } if (!TryWriteByte(bytes[5], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteByte(bytes[4], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (dash) { if (!TryWriteChar('-', buffer, formattingData, ref bytesWritten)) { return false; } } if (!TryWriteByte(bytes[7], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteByte(bytes[6], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (dash) { if (!TryWriteChar('-', buffer, formattingData, ref bytesWritten)) { return false; } } if (!TryWriteByte(bytes[8], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteByte(bytes[9], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (dash) { if (!TryWriteChar('-', buffer, formattingData, ref bytesWritten)) { return false; } } if (!TryWriteByte(bytes[10], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteByte(bytes[11], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteByte(bytes[12], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteByte(bytes[13], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteByte(bytes[14], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } if (!TryWriteByte(bytes[15], buffer, byteFormat, formattingData, ref bytesWritten)) { return false; } } if (tail != '\0') { if (!TryWriteChar(tail, buffer, formattingData, ref bytesWritten)) { return false; } } return true; }
public static bool TryFormat(this TimeSpan value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if (format.IsDefault) { format.Symbol = 'c'; } Precondition.Require(format.Symbol == 'G' || format.Symbol == 't' || format.Symbol == 'c' || format.Symbol == 'g'); if (format.Symbol != 't') { return TryFormatTimeSpanG(value, buffer, format, formattingData, out bytesWritten); } // else it's format 't' (short time used to print time offsets) return TryFormatTimeSpanT(value, buffer, formattingData, out bytesWritten); }
public static bool TryFormat(this string value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if (formattingData.IsUtf16) { var valueBytes = value.Length << 1; if (valueBytes > buffer.Length) { bytesWritten = 0; return false; } unsafe { fixed (char* pCharacters = value) { byte* pBytes = (byte*)pCharacters; buffer.Set(pBytes, valueBytes); } } bytesWritten = valueBytes; return true; } GCHandle handle; var byteSpan = buffer.Pin(out handle); try { var avaliableBytes = byteSpan.Length; bytesWritten = 0; for (int i = 0; i < value.Length; i++) { var c = value[i]; var codepoint = (ushort)c; if (codepoint <= 0x7f) // this if block just optimizes for ascii { if (bytesWritten + 1 > avaliableBytes) { bytesWritten = 0; return false; } byteSpan[bytesWritten++] = (byte)codepoint; } else { var encoded = new FourBytes(); var bytes = Utf8Encoder.CharToUtf8(c, ref encoded); if (bytesWritten + bytes > avaliableBytes) { bytesWritten = 0; return false; } byteSpan[bytesWritten] = encoded.B0; if (bytes > 1) { byteSpan[bytesWritten + 1] = encoded.B1; if (bytes > 2) { byteSpan[bytesWritten + 2] = encoded.B2; if (bytes > 3) { byteSpan[bytesWritten + 3] = encoded.B3; } } } bytesWritten += bytes; } } return true; } finally { handle.Free(); } }
static bool TryWriteInt64(long i, Span<byte> buffer, Format.Parsed byteFormat, FormattingData formattingData, ref int bytesWritten) { int written; if (!i.TryFormat(buffer.Slice(bytesWritten), byteFormat, formattingData, out written)) { bytesWritten = 0; return false; } bytesWritten += written; return true; }
public static bool TryFormat(this Utf8String value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if (formattingData.IsUtf16) { throw new NotImplementedException(); } if(buffer.Length < value.Length) { bytesWritten = 0; return false; } buffer.Set(value.Bytes); bytesWritten = value.Length; return true; }
// TODO: this whole routine is too slow. It does div and mod twice, which are both costly (especially that some JITs cannot optimize it). // It does it twice to avoid reversing the formatted buffer, which can be tricky given it should handle arbitrary cultures. // One optimization I thought we could do is to do div/mod once and store digits in a temp buffer (but that would allocate). Modification to the idea would be to store the digits in a local struct // Another idea possibly worth tying would be to special case cultures that have constant digit size, and go back to the format + reverse buffer approach. private static bool TryFormatDecimal(ulong value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if(format.IsDefault) { format.Symbol = 'G'; } format.Symbol = Char.ToUpperInvariant(format.Symbol); // TODO: this is costly. I think the transformation should happen in Parse Precondition.Require(format.Symbol == 'D' || format.Symbol == 'G' || format.Symbol == 'N'); // Reverse value on decimal basis, count digits and trailing zeros before the decimal separator ulong reversedValueExceptFirst = 0; var digitsCount = 1; var trailingZerosCount = 0; // We reverse the digits in numeric form because reversing encoded digits is hard and/or costly. // If value contains 20 digits, its reversed value will not fit into ulong size. // So reverse it till last digit (reversedValueExceptFirst will have all the digits except the first one). while (value >= 10) { var digit = value % 10UL; value = value / 10UL; if (reversedValueExceptFirst == 0 && digit == 0) { trailingZerosCount++; } else { reversedValueExceptFirst = reversedValueExceptFirst * 10UL + digit; digitsCount++; } } bytesWritten = 0; int digitBytes; // If format is D and precision is greater than digitsCount + trailingZerosCount, append leading zeros if (format.Symbol == 'D' && format.HasPrecision) { var leadingZerosCount = format.Precision - digitsCount - trailingZerosCount; while (leadingZerosCount-- > 0) { if (!formattingData.TryWriteDigitOrSymbol(0, buffer.Slice(bytesWritten), out digitBytes)) { bytesWritten = 0; return false; } bytesWritten += digitBytes; } } // Append first digit if (!formattingData.TryWriteDigit(value, buffer.Slice(bytesWritten), out digitBytes)) { bytesWritten = 0; return false; } bytesWritten += digitBytes; digitsCount--; if (format.Symbol == 'N') { const int GroupSize = 3; // Count amount of digits before first group separator. It will be reset to groupSize every time digitsLeftInGroup == zero var digitsLeftInGroup = (digitsCount + trailingZerosCount) % GroupSize; if (digitsLeftInGroup == 0) { if (digitsCount + trailingZerosCount > 0) { // There is a new group immediately after the first digit if (!formattingData.TryWriteSymbol(FormattingData.Symbol.GroupSeparator, buffer.Slice(bytesWritten), out digitBytes)) { bytesWritten = 0; return false; } bytesWritten += digitBytes; } digitsLeftInGroup = GroupSize; } // Append digits while (reversedValueExceptFirst > 0) { if (digitsLeftInGroup == 0) { if (!formattingData.TryWriteSymbol(FormattingData.Symbol.GroupSeparator, buffer.Slice(bytesWritten), out digitBytes)) { bytesWritten = 0; return false; } bytesWritten += digitBytes; digitsLeftInGroup = GroupSize; } var nextDigit = reversedValueExceptFirst % 10UL; reversedValueExceptFirst = reversedValueExceptFirst / 10UL; if (!formattingData.TryWriteDigit(nextDigit, buffer.Slice(bytesWritten), out digitBytes)) { bytesWritten = 0; return false; } bytesWritten += digitBytes; digitsLeftInGroup--; } // Append trailing zeros if any while (trailingZerosCount-- > 0) { if (digitsLeftInGroup == 0) { if (!formattingData.TryWriteSymbol(FormattingData.Symbol.GroupSeparator, buffer.Slice(bytesWritten), out digitBytes)) { bytesWritten = 0; return false; } bytesWritten += digitBytes; digitsLeftInGroup = GroupSize; } if (!formattingData.TryWriteDigitOrSymbol(0, buffer.Slice(bytesWritten), out digitBytes)) { bytesWritten = 0; return false; } bytesWritten += digitBytes; digitsLeftInGroup--; } } else { while (reversedValueExceptFirst > 0) { var bufferSlice = buffer.Slice(bytesWritten); var nextDigit = reversedValueExceptFirst % 10UL; reversedValueExceptFirst = reversedValueExceptFirst / 10UL; if (!formattingData.TryWriteDigit(nextDigit, bufferSlice, out digitBytes)) { bytesWritten = 0; return false; } bytesWritten += digitBytes; } // Append trailing zeros if any while (trailingZerosCount-- > 0) { if (!formattingData.TryWriteDigitOrSymbol(0, buffer.Slice(bytesWritten), out digitBytes)) { bytesWritten = 0; return false; } bytesWritten += digitBytes; } } // If format is N and precision is not defined or is greater than zero, append trailing zeros after decimal point if (format.Symbol == 'N') { int trailingZerosAfterDecimalCount = format.HasPrecision ? format.Precision : 2; if (trailingZerosAfterDecimalCount > 0) { if (!formattingData.TryWriteSymbol(FormattingData.Symbol.DecimalSeparator, buffer.Slice(bytesWritten), out digitBytes)) { bytesWritten = 0; return false; } bytesWritten += digitBytes; while (trailingZerosAfterDecimalCount-- > 0) { if (!formattingData.TryWriteDigitOrSymbol(0, buffer.Slice(bytesWritten), out digitBytes)) { bytesWritten = 0; return false; } bytesWritten += digitBytes; } } } return true; }
private static bool TryFormatHexadecimalInvariantCultureUtf8(ulong value, Span<byte> buffer, Format.Parsed format, out int bytesWritten) { Precondition.Require(format.Symbol == 'X' || format.Symbol == 'X'); byte firstDigitOffset = (byte)'0'; byte firstHexCharOffset = format.Symbol == 'X' ? (byte)'a' : (byte)'A'; firstHexCharOffset -= 10; // Count amount of hex digits var hexDigitsCount = 1; ulong valueToCount = value; if (valueToCount > 0xFFFFFFFF) { hexDigitsCount += 8; valueToCount >>= 0x20; } if (valueToCount > 0xFFFF) { hexDigitsCount += 4; valueToCount >>= 0x10; } if (valueToCount > 0xFF) { hexDigitsCount += 2; valueToCount >>= 0x8; } if (valueToCount > 0xF) { hexDigitsCount++; } var bytesCount = hexDigitsCount; // Count leading zeros var leadingZerosCount = format.HasPrecision ? format.Precision - hexDigitsCount : 0; bytesCount += leadingZerosCount > 0 ? leadingZerosCount : 0; if (bytesCount > buffer.Length) { bytesWritten = 0; return false; } var index = bytesCount; while (hexDigitsCount-- > 0) { byte digit = (byte)(value & 0xF); value >>= 0x4; digit += digit < 10 ? firstDigitOffset : firstHexCharOffset; buffer[--index] = digit; } // Write leading zeros if any while (leadingZerosCount-- > 0) { buffer[--index] = firstDigitOffset; } bytesWritten = bytesCount; return true; }
public static bool TryFormat(this string value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { if (formattingData.IsUtf16) { var valueBytes = value.Length << 1; if (valueBytes > buffer.Length) { bytesWritten = 0; return false; } unsafe { fixed (char* pCharacters = value) { byte* pBytes = (byte*)pCharacters; buffer.Set(pBytes, valueBytes); } } bytesWritten = valueBytes; return true; } GCHandle handle; var byteSpan = buffer.Pin(out handle); try { var avaliableBytes = byteSpan.Length; bytesWritten = 0; for (int i = 0; i < value.Length; i++) { var c = value[i]; var codepoint = (ushort)c; if (codepoint <= 0x7f) // this if block just optimizes for ascii { if (bytesWritten + 1 > avaliableBytes) { bytesWritten = 0; return false; } byteSpan[bytesWritten++] = (byte)codepoint; } else { Utf8EncodedCodePoint encoded; if (!char.IsSurrogate(c)) encoded = new Utf8EncodedCodePoint(c); else { if (++i >= value.Length) throw new ArgumentException("value", "Invalid surrogate pair."); char lowSurrogate = value[i]; encoded = new Utf8EncodedCodePoint(c, lowSurrogate); } if (bytesWritten + encoded.Length > avaliableBytes) { bytesWritten = 0; return false; } byteSpan[bytesWritten] = encoded.Byte0; if (encoded.Length > 1) { byteSpan[bytesWritten + 1] = encoded.Byte1; if (encoded.Length > 2) { byteSpan[bytesWritten + 2] = encoded.Byte2; if (encoded.Length > 3) { byteSpan[bytesWritten + 3] = encoded.Byte3; } } } bytesWritten += encoded.Length; } } return true; } finally { handle.Free(); } }
public static bool TryFormat(this long value, Span<byte> buffer, Format.Parsed format, FormattingData formattingData, out int bytesWritten) { return IntegerFormatter.TryFormatInt64(value, 8, buffer, format, formattingData, out bytesWritten); }