public DateTimeOffset Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) { var str = reader.ReadStringSegmentUnsafe(); var array = str.Array; var i = str.Offset; var len = str.Count; var to = str.Offset + str.Count; // YYYY if (len == 4) { var y = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); return(new DateTimeOffset(y, 1, 1, 0, 0, 0, TimeSpan.Zero)); } // YYYY-MM if (len == 7) { var y = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); return(new DateTimeOffset(y, m, 1, 0, 0, 0, TimeSpan.Zero)); } // YYYY-MM-DD if (len == 10) { var y = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var d = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); return(new DateTimeOffset(y, m, d, 0, 0, 0, TimeSpan.Zero)); } // range-first section requires 19 if (array.Length < 19) { goto ERROR; } var year = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var month = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var day = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'T') { goto ERROR; } var hour = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var minute = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var second = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); int ticks = 0; if (i < to && array[i] == '.') { i++; // *7. if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1; i++; // others, lack of precision while (i < to && NumberConverter.IsNumber(array[i])) { i++; } } END_TICKS: if (i < to && array[i] == '-' || array[i] == '+') { if (!(i + 5 < to)) { goto ERROR; } var minus = array[i++] == '-'; var h = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); i++; var m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); var offset = new TimeSpan(h, m, 0); if (minus) { offset = offset.Negate(); } return(new DateTimeOffset(year, month, day, hour, minute, second, offset).AddTicks(ticks)); } return(new DateTimeOffset(year, month, day, hour, minute, second, TimeSpan.Zero).AddTicks(ticks)); ERROR: throw new InvalidOperationException("invalid datetime format. value:" + StringEncoding.UTF8.GetString(str.Array, str.Offset, str.Count)); }
public TimeSpan Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) { var str = reader.ReadStringSegmentUnsafe(); var array = str.Array; var i = str.Offset; var len = str.Count; var to = str.Offset + str.Count; // check day exists bool hasDay = false; { bool foundDot = false; bool foundColon = false; for (int j = i; j < str.Count; j++) { if (array[j] == '.') { if (foundColon) { break; } foundDot = true; } else if (array[j] == ':') { if (foundDot) { hasDay = true; } foundColon = true; } } } // check sign var minus = false; if (array[i] == '-') { minus = true; i++; } var day = 0; if (hasDay) { var poolArray = BufferPool.Default.Rent(); try { for (; array[i] != '.'; i++) { poolArray[day++] = array[i]; } day = new JsonReader(poolArray).ReadInt32(); i++; // skip '.' } finally { BufferPool.Default.Return(poolArray); } } var hour = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var minute = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var second = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); int ticks = 0; if (i < to && array[i] == '.') { i++; // *7. if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1; i++; // others, lack of precision while (i < to && NumberConverter.IsNumber(array[i])) { i++; } } END_TICKS: // be careful to overflow var ts = new TimeSpan(day, hour, minute, second); var tk = TimeSpan.FromTicks(ticks); return((minus) ? ts.Negate().Subtract(tk) : ts.Add(tk)); ERROR: throw new InvalidOperationException("invalid datetime format. value:" + StringEncoding.UTF8.GetString(str.Array, str.Offset, str.Count)); }
public TimeSpan Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) { var str = reader.ReadStringSegmentUnsafe(); var array = str.Array; var i = str.Offset; var len = str.Count; var to = str.Offset + len; // check day exists var hasDay = false; { var foundDot = false; var foundColon = false; for (var j = i; j < to; j++) { if (array[j] == '.') { if (foundColon) { break; } foundDot = true; } else if (array[j] == ':') { if (foundDot) { hasDay = true; } foundColon = true; } } } // check sign var minus = false; if (array[i] == '-') { minus = true; i++; } var day = 0; if (hasDay) { const int maxDayLength = 8 + 1; // {Day}. var dayCharacters = new byte[maxDayLength]; for (; array[i] != '.'; i++) { dayCharacters[day++] = array[i]; } day = new JsonReader(dayCharacters).ReadInt32(); i++; // skip '.' } var hour = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var minute = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var second = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); var ticks = 0; if (i < to && array[i] == '.') { i++; // *7. if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1; i++; // others, lack of precision while (i < to && NumberConverter.IsNumber(array[i])) { i++; } } END_TICKS: // be careful to overflow var ts = new TimeSpan(day, hour, minute, second); var tk = TimeSpan.FromTicks(ticks); return(minus ? ts.Negate().Subtract(tk) : ts.Add(tk)); ERROR: throw new InvalidOperationException("invalid TimeSpan format. value:" + StringEncoding.UTF8.GetString(str.Array, str.Offset, str.Count)); }
public DateTime Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) { var str = reader.ReadStringSegmentUnsafe(); var array = str.Array; var i = str.Offset; var len = str.Count; var to = str.Offset + str.Count; // YYYY if (len == 4) { var y = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); return(new DateTime(y, 1, 1)); } // YYYY-MM if (len == 7) { var y = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); return(new DateTime(y, m, 1)); } // YYYY-MM-DD if (len == 10) { var y = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var d = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); return(new DateTime(y, m, d)); } // range-first section requires 19 if (len < 19) { goto ERROR; } var year = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var month = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var day = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'T') { goto ERROR; } var hour = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var minute = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var second = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); var ticks = 0; if (i < to && array[i] == '.') { i++; // *7. if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1; i++; // others, lack of precision while (i < to && NumberConverter.IsNumber(array[i])) { i++; } } END_TICKS: var kind = DateTimeKind.Unspecified; if (i < to && array[i] == 'Z') { kind = DateTimeKind.Utc; } else if (i < to && array[i] == '-' || array[i] == '+') { var offLen = to - i; if (offLen != 3 && offLen != 5 && offLen != 6) { goto ERROR; } var minus = array[i++] == '-'; var h = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); var m = 0; if (i < to) { if (offLen == 6) { if (array[i] != ':') { goto ERROR; } i++; } m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); } var offset = new TimeSpan(h, m, 0); if (minus) { offset = offset.Negate(); } return(new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc).AddTicks(ticks).Subtract(offset).ToLocalTime()); } return(new DateTime(year, month, day, hour, minute, second, kind).AddTicks(ticks)); ERROR: throw new InvalidOperationException("invalid datetime format. value:" + StringEncoding.UTF8.GetString(str.Array, str.Offset, str.Count)); }
void ReadStringSegmentCore(out byte[] resultBytes, out int resultOffset, out int resultLength) { // SkipWhiteSpace is already called from IsNull byte[] builder = null; var builderOffset = 0; char[] codePointStringBuffer = null; var codePointStringOffet = 0; var isNumberAsString = false; if (NumberConverter.IsNumber(bytes[offset]) || (bytes[offset] == '-' && NumberConverter.IsNumber(bytes[offset + 1]))) { isNumberAsString = true; } if (!isNumberAsString) { if (bytes[offset] != '\"') { throw CreateParsingException("String Begin Token"); } offset++; } var from = offset; // eliminate array-bound check for (int i = offset; i < bytes.Length; i++) { byte escapeCharacter = 0; switch (bytes[i]) { case (byte)'\\': // escape character switch ((char)bytes[i + 1]) { case '"': case '\\': case '/': escapeCharacter = bytes[i + 1]; goto COPY; case 'b': escapeCharacter = (byte)'\b'; goto COPY; case 'f': escapeCharacter = (byte)'\f'; goto COPY; case 'n': escapeCharacter = (byte)'\n'; goto COPY; case 'r': escapeCharacter = (byte)'\r'; goto COPY; case 't': escapeCharacter = (byte)'\t'; goto COPY; case 'u': if (codePointStringBuffer == null) { codePointStringBuffer = StringBuilderCache.GetCodePointStringBuffer(); } if (codePointStringOffet == 0) { if (builder == null) { builder = StringBuilderCache.GetBuffer(); } var copyCount = i - from; BinaryUtil.EnsureCapacity(ref builder, builderOffset, copyCount + 1); // require + 1 Buffer.BlockCopy(bytes, from, builder, builderOffset, copyCount); builderOffset += copyCount; } if (codePointStringBuffer.Length == codePointStringOffet) { Array.Resize(ref codePointStringBuffer, codePointStringBuffer.Length * 2); } var a = (char)bytes[i + 2]; var b = (char)bytes[i + 3]; var c = (char)bytes[i + 4]; var d = (char)bytes[i + 5]; var codepoint = GetCodePoint(a, b, c, d); codePointStringBuffer[codePointStringOffet++] = (char)codepoint; i += 5; offset += 6; from = offset; continue; default: throw CreateParsingExceptionMessage("Bad JSON escape."); } case (byte)'"': // endtoken offset++; goto END; default: // string if (codePointStringOffet != 0) { if (builder == null) { builder = StringBuilderCache.GetBuffer(); } BinaryUtil.EnsureCapacity(ref builder, builderOffset, StringEncoding.UTF8.GetMaxByteCount(codePointStringOffet)); builderOffset += StringEncoding.UTF8.GetBytes(codePointStringBuffer, 0, codePointStringOffet, builder, builderOffset); codePointStringOffet = 0; } offset++; if (isNumberAsString && !NumberConverter.IsNumber(bytes[i]) && bytes[i] != '.') { offset--; goto END; } continue; } COPY: { if (builder == null) { builder = StringBuilderCache.GetBuffer(); } if (codePointStringOffet != 0) { BinaryUtil.EnsureCapacity(ref builder, builderOffset, StringEncoding.UTF8.GetMaxByteCount(codePointStringOffet)); builderOffset += StringEncoding.UTF8.GetBytes(codePointStringBuffer, 0, codePointStringOffet, builder, builderOffset); codePointStringOffet = 0; } var copyCount = i - from; BinaryUtil.EnsureCapacity(ref builder, builderOffset, copyCount + 1); // require + 1! Buffer.BlockCopy(bytes, from, builder, builderOffset, copyCount); builderOffset += copyCount; builder[builderOffset++] = escapeCharacter; i += 1; offset += 2; from = offset; } } resultLength = 0; resultBytes = null; resultOffset = 0; throw CreateParsingException("String End Token"); END: if (builderOffset == 0 && codePointStringOffet == 0) // no escape { resultBytes = bytes; resultOffset = from; if (isNumberAsString) { resultLength = offset - from; } else { resultLength = offset - 1 - from; // skip last quote } } else { if (builder == null) { builder = StringBuilderCache.GetBuffer(); } if (codePointStringOffet != 0) { BinaryUtil.EnsureCapacity(ref builder, builderOffset, StringEncoding.UTF8.GetMaxByteCount(codePointStringOffet)); builderOffset += StringEncoding.UTF8.GetBytes(codePointStringBuffer, 0, codePointStringOffet, builder, builderOffset); codePointStringOffet = 0; } var copyCount = offset - from - 1; BinaryUtil.EnsureCapacity(ref builder, builderOffset, copyCount); Buffer.BlockCopy(bytes, from, builder, builderOffset, copyCount); builderOffset += copyCount; resultBytes = builder; resultOffset = 0; resultLength = builderOffset; } }