internal static void WriteValue(int value, JsonSerializerHandler handler) { // Gotta special case this, we can't negate it if (value == int.MinValue) { handler.WriteString("-2147483648"); return; } if (value == int.MaxValue) { handler.WriteString("2147483647"); return; } var ptr = 35; char[] buffer = new char[36]; uint copy; if (value < 0) { handler.WriteChar('-'); copy = (uint)(-value); } else { copy = (uint)value; } do { byte ix = (byte)(copy % 100); copy /= 100; var chars = SpecialTypeNormal.DigitPairs[ix]; buffer[ptr--] = chars.Second; buffer[ptr--] = chars.First; } while (copy != 0); if (buffer[ptr + 1] == '0') { ptr++; } handler.WriteChars(buffer, ptr + 1, 35 - ptr); }
internal static void WriteValue(long value, JsonSerializerHandler handler) { if (value == long.MinValue) { handler.WriteString("-9223372036854775808"); return; } char[] buffer = new char[36]; var ptr = 35; ulong copy; if (value < 0) { handler.WriteChar('-'); copy = (ulong)(-value); } else { copy = (ulong)value; } do { byte ix = (byte)(copy % 100); copy /= 100; var chars = SpecialTypeNormal.DigitPairs[ix]; buffer[ptr--] = chars.Second; buffer[ptr--] = chars.First; } while (copy != 0); if (buffer[ptr + 1] == '0') { ptr++; } handler.WriteChars(buffer, ptr + 1, 35 - ptr); }
internal static unsafe void WriteValue(string value, JsonSerializerHandler handler) { /* * string = quotation-mark *char quotation-mark * * char = unescaped / * escape ( * %x22 / ; " quotation mark U+0022 * %x5C / ; \ reverse solidus U+005C * %x2F / ; / solidus U+002F * %x62 / ; b backspace U+0008 * %x66 / ; f form feed U+000C * %x6E / ; n line feed U+000A * %x72 / ; r carriage return U+000D * %x74 / ; t tab U+0009 * %x75 4HEXDIG ) ; uXXXX U+XXXX * * escape = %x5C ; \ * * quotation-mark = %x22 ; " * * unescaped = %x20-21 / %x23-5B / %x5D-10FFFF */ if (value == null) { handler.WriteString("null"); return; } //handler.Writer.EnsureCapacity(handler.Writer.Capacity + value.Length); handler.WriteString("\""); fixed(char *strFixed = value) { char *str = strFixed; char c; var len = value.Length; while (len > 0) { c = *str; str++; len--; if (c == '\\')//\u005c //%x5c a\\b => a\u005cb { handler.WriteString(@"\\"); continue; } if (c == '"')//\u0022 //%x22 { handler.WriteString("\\\""); continue; } switch (c) { //%x00-x19 case '\u0000': handler.WriteString(@"\u0000"); continue; case '\u0001': handler.WriteString(@"\u0001"); continue; case '\u0002': handler.WriteString(@"\u0002"); continue; case '\u0003': handler.WriteString(@"\u0003"); continue; case '\u0004': handler.WriteString(@"\u0004"); continue; case '\u0005': handler.WriteString(@"\u0005"); continue; case '\u0006': handler.WriteString(@"\u0006"); continue; case '\u0007': handler.WriteString(@"\u0007"); continue; case '\u0008': handler.WriteString(@"\b"); continue; case '\u0009': handler.WriteString(@"\t"); continue; case '\u000A': handler.WriteString(@"\n"); continue; case '\u000B': handler.WriteString(@"\u000b"); continue; case '\u000C': handler.WriteString(@"\f"); continue; case '\u000D': handler.WriteString(@"\r"); continue; case '\u000E': handler.WriteString(@"\u000e"); continue; case '\u000F': handler.WriteString(@"\u000f"); continue; case '\u0010': handler.WriteString(@"\u0010"); continue; case '\u0011': handler.WriteString(@"\u0011"); continue; case '\u0012': handler.WriteString(@"\u0012"); continue; case '\u0013': handler.WriteString(@"\u0013"); continue; case '\u0014': handler.WriteString(@"\u0014"); continue; case '\u0015': handler.WriteString(@"\u0015"); continue; case '\u0016': handler.WriteString(@"\u0016"); continue; case '\u0017': handler.WriteString(@"\u0017"); continue; case '\u0018': handler.WriteString(@"\u0018"); continue; case '\u0019': handler.WriteString(@"\u0019"); continue; case '\u001A': handler.WriteString(@"\u001a"); continue; case '\u001B': handler.WriteString(@"\u001b"); continue; case '\u001C': handler.WriteString(@"\u001c"); continue; case '\u001D': handler.WriteString(@"\u001d"); continue; case '\u001E': handler.WriteString(@"\u001e"); continue; case '\u001F': handler.WriteString(@"\u001f"); continue; /*JavaScript */ case '\u0085': // Next Line handler.WriteString(@"\u0085"); continue; case '\u2028': // Line Separator handler.WriteString(@"\u2028"); continue; case '\u2029': // Paragraph Separator handler.WriteString(@"\u2029"); continue; default: handler.WriteChar(c); continue; } } } handler.WriteString("\""); }
internal static void WriteValue(StringBuilder value, JsonSerializerHandler handler) { if (value == null) { handler.WriteString("null"); } else { handler.WriteString("\""); for (int i = 0; i < value.Length; i++) { char c = value[i]; if (c == '\\')//\u005c //%x5c a\\b => a\u005cb { handler.WriteString(@"\\"); continue; } if (c == '"')//\u0022 //%x22 { handler.WriteString("\\\""); continue; } //如果是jsonp格式,多了 u2028 u2029的转换 switch (c) { //%x00-x19 case '\u0000': handler.WriteString(@"\u0000"); continue; case '\u0001': handler.WriteString(@"\u0001"); continue; case '\u0002': handler.WriteString(@"\u0002"); continue; case '\u0003': handler.WriteString(@"\u0003"); continue; case '\u0004': handler.WriteString(@"\u0004"); continue; case '\u0005': handler.WriteString(@"\u0005"); continue; case '\u0006': handler.WriteString(@"\u0006"); continue; case '\u0007': handler.WriteString(@"\u0007"); continue; case '\u0008': handler.WriteString(@"\b"); continue; case '\u0009': handler.WriteString(@"\t"); continue; case '\u000A': handler.WriteString(@"\n"); continue; case '\u000B': handler.WriteString(@"\u000b"); continue; case '\u000C': handler.WriteString(@"\f"); continue; case '\u000D': handler.WriteString(@"\r"); continue; case '\u000E': handler.WriteString(@"\u000e"); continue; case '\u000F': handler.WriteString(@"\u000f"); continue; case '\u0010': handler.WriteString(@"\u0010"); continue; case '\u0011': handler.WriteString(@"\u0011"); continue; case '\u0012': handler.WriteString(@"\u0012"); continue; case '\u0013': handler.WriteString(@"\u0013"); continue; case '\u0014': handler.WriteString(@"\u0014"); continue; case '\u0015': handler.WriteString(@"\u0015"); continue; case '\u0016': handler.WriteString(@"\u0016"); continue; case '\u0017': handler.WriteString(@"\u0017"); continue; case '\u0018': handler.WriteString(@"\u0018"); continue; case '\u0019': handler.WriteString(@"\u0019"); continue; case '\u001A': handler.WriteString(@"\u001a"); continue; case '\u001B': handler.WriteString(@"\u001b"); continue; case '\u001C': handler.WriteString(@"\u001c"); continue; case '\u001D': handler.WriteString(@"\u001d"); continue; case '\u001E': handler.WriteString(@"\u001e"); continue; case '\u001F': handler.WriteString(@"\u001f"); continue; default: handler.WriteChar(c); continue; } } handler.WriteString("\""); } }
internal static void WriteValue(TimeSpan value, JsonSerializerHandler handler) { if (handler.Option.TimespanFormat == TimespanFormatEnum.ISO8601) { // can't negate this, have to handle it manually if (value.Ticks == long.MinValue) { handler.WriteString("\"-P10675199DT2H48M5.4775808S\""); return; } char[] buffer = new char[36]; handler.WriteChar('"'); if (value.Ticks < 0) { handler.WriteChar('-'); value = value.Negate(); } handler.WriteChar('P'); var days = value.Days; var hours = value.Hours; var minutes = value.Minutes; var seconds = value.Seconds; // days if (days > 0) { _CustomWriteIntUnrolledSigned(handler, days, buffer); handler.WriteChar('D'); } // time separator handler.WriteChar('T'); // hours if (hours > 0) { _CustomWriteIntUnrolledSigned(handler, hours, buffer); handler.WriteChar('H'); } // minutes if (minutes > 0) { _CustomWriteIntUnrolledSigned(handler, minutes, buffer); handler.WriteChar('M'); } // seconds _CustomWriteIntUnrolledSigned(handler, seconds, buffer); // fractional part { var endCount = 0; var remainingTicks = (value - new TimeSpan(days, hours, minutes, seconds, 0)).Ticks; if (remainingTicks > 0) { int fracEnd; buffer[0] = '.'; var fracPart = remainingTicks % 100; remainingTicks /= 100; TwoDigits digits; if (fracPart > 0) { digits = DigitPairs[fracPart]; buffer[7] = digits.Second; buffer[6] = digits.First; fracEnd = 8; } else { fracEnd = 6; } fracPart = remainingTicks % 100; remainingTicks /= 100; if (fracPart > 0) { digits = DigitPairs[fracPart]; buffer[5] = digits.Second; buffer[4] = digits.First; } else { if (fracEnd == 6) { fracEnd = 4; } else { buffer[5] = '0'; buffer[4] = '0'; } } fracPart = remainingTicks % 100; remainingTicks /= 100; if (fracPart > 0) { digits = DigitPairs[fracPart]; buffer[3] = digits.Second; buffer[2] = digits.First; } else { if (fracEnd == 4) { fracEnd = 2; } else { buffer[3] = '0'; buffer[2] = '0'; } } fracPart = remainingTicks; buffer[1] = (char)('0' + fracPart); endCount = fracEnd; } handler.WriteChars(buffer, 0, endCount); } handler.WriteString("S\""); } else { if (value.Ticks == long.MinValue) { handler.WriteString("\"-10675199.02:48:05.4775808\""); return; } char[] buffer = new char[36]; handler.WriteChar('"'); if (value.Ticks < 0) { handler.WriteChar('-'); value = value.Negate(); } var days = value.Days; var hours = value.Hours; var minutes = value.Minutes; var secs = value.Seconds; TwoDigits digits; // days { if (days != 0) { PrimitiveNormal.WriteValue(days, handler); handler.WriteChar('.'); } } // hours { digits = DigitPairs[hours]; buffer[0] = digits.First; buffer[1] = digits.Second; } buffer[2] = ':'; // minutes { digits = DigitPairs[minutes]; buffer[3] = digits.First; buffer[4] = digits.Second; } buffer[5] = ':'; // seconds { digits = DigitPairs[secs]; buffer[6] = digits.First; buffer[7] = digits.Second; } int endCount = 8; // factional part { var remainingTicks = (value - new TimeSpan(value.Days, value.Hours, value.Minutes, value.Seconds, 0)).Ticks; if (remainingTicks > 0) { int fracEnd; buffer[8] = '.'; var fracPart = remainingTicks % 100; remainingTicks /= 100; if (fracPart > 0) { digits = DigitPairs[fracPart]; buffer[15] = digits.Second; buffer[14] = digits.First; fracEnd = 16; } else { fracEnd = 14; } fracPart = remainingTicks % 100; remainingTicks /= 100; if (fracPart > 0) { digits = DigitPairs[fracPart]; buffer[13] = digits.Second; buffer[12] = digits.First; } else { if (fracEnd == 14) { fracEnd = 12; } else { buffer[13] = '0'; buffer[12] = '0'; } } fracPart = remainingTicks % 100; remainingTicks /= 100; if (fracPart > 0) { digits = DigitPairs[fracPart]; buffer[11] = digits.Second; buffer[10] = digits.First; } else { if (fracEnd == 12) { fracEnd = 10; } else { buffer[11] = '0'; buffer[10] = '0'; } } fracPart = remainingTicks; buffer[9] = (char)('0' + fracPart); endCount = fracEnd; } } handler.WriteChars(buffer, 0, endCount); handler.WriteChar('"'); } }
internal static void WriteValue(DateTime value, JsonSerializerHandler handler) { if (handler.Option.DatetimeFormat == DatetimeFormatEnum.ISO8601) { // "yyyy-mm-ddThh:mm:ss.fffffffZ" // 0123456789ABCDEFGHIJKL // // Yes, DateTime.Max is in fact guaranteed to have a 4 digit year (and no more) // f of 7 digits allows for 1 Tick level resolution char[] buffer = new char[36]; buffer[0] = '"'; // Year uint val = (uint)value.Year; var digits = DigitPairs[(byte)(val % 100)]; buffer[4] = digits.Second; buffer[3] = digits.First; digits = DigitPairs[(byte)(val / 100)]; buffer[2] = digits.Second; buffer[1] = digits.First; // delimiter buffer[5] = '-'; // Month digits = DigitPairs[value.Month]; buffer[7] = digits.Second; buffer[6] = digits.First; // Delimiter buffer[8] = '-'; // Day digits = DigitPairs[value.Day]; buffer[10] = digits.Second; buffer[9] = digits.First; // Delimiter buffer[11] = 'T'; digits = DigitPairs[value.Hour]; buffer[13] = digits.Second; buffer[12] = digits.First; // Delimiter buffer[14] = ':'; digits = DigitPairs[value.Minute]; buffer[16] = digits.Second; buffer[15] = digits.First; // Delimiter buffer[17] = ':'; digits = DigitPairs[value.Second]; buffer[19] = digits.Second; buffer[18] = digits.First; int fracEnd; var remainingTicks = (value - new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second)).Ticks; if (remainingTicks > 0) { buffer[20] = '.'; var fracPart = remainingTicks % 100; remainingTicks /= 100; if (fracPart > 0) { digits = DigitPairs[fracPart]; buffer[27] = digits.Second; buffer[26] = digits.First; fracEnd = 28; } else { fracEnd = 26; } fracPart = remainingTicks % 100; remainingTicks /= 100; if (fracPart > 0) { digits = DigitPairs[fracPart]; buffer[25] = digits.Second; buffer[24] = digits.First; } else { if (fracEnd == 26) { fracEnd = 24; } else { buffer[25] = '0'; buffer[24] = '0'; } } fracPart = remainingTicks % 100; remainingTicks /= 100; if (fracPart > 0) { digits = DigitPairs[fracPart]; buffer[23] = digits.Second; buffer[22] = digits.First; } else { if (fracEnd == 24) { fracEnd = 22; } else { buffer[23] = '0'; buffer[22] = '0'; } } fracPart = remainingTicks; buffer[21] = (char)('0' + fracPart); } else { fracEnd = 20; } buffer[fracEnd] = 'Z'; buffer[fracEnd + 1] = '"'; handler.WriteChars(buffer, 0, fracEnd + 2); } else if (handler.Option.DatetimeFormat == DatetimeFormatEnum.RFC1123) { // ddd, dd MMM yyyy HH:mm:ss GMT'" handler.WriteChar('"'); // compiles as a switch switch (value.DayOfWeek) { case DayOfWeek.Sunday: handler.WriteString("Sun, "); break; case DayOfWeek.Monday: handler.WriteString("Mon, "); break; case DayOfWeek.Tuesday: handler.WriteString("Tue, "); break; case DayOfWeek.Wednesday: handler.WriteString("Wed, "); break; case DayOfWeek.Thursday: handler.WriteString("Thu, "); break; case DayOfWeek.Friday: handler.WriteString("Fri, "); break; case DayOfWeek.Saturday: handler.WriteString("Sat, "); break; } { var day = DigitPairs[value.Day]; handler.WriteChar(day.First); handler.WriteChar(day.Second); handler.WriteChar(' '); } // compiles as a switch switch (value.Month) { case 1: handler.WriteString("Jan "); break; case 2: handler.WriteString("Feb "); break; case 3: handler.WriteString("Mar "); break; case 4: handler.WriteString("Apr "); break; case 5: handler.WriteString("May "); break; case 6: handler.WriteString("Jun "); break; case 7: handler.WriteString("Jul "); break; case 8: handler.WriteString("Aug "); break; case 9: handler.WriteString("Sep "); break; case 10: handler.WriteString("Oct "); break; case 11: handler.WriteString("Nov "); break; case 12: handler.WriteString("Dec "); break; } { var year = value.Year; var firstHalfYear = DigitPairs[year / 100]; handler.WriteChar(firstHalfYear.First); handler.WriteChar(firstHalfYear.Second); var secondHalfYear = DigitPairs[year % 100]; handler.WriteChar(secondHalfYear.First); handler.WriteChar(secondHalfYear.Second); handler.WriteChar(' '); } { var hour = DigitPairs[value.Hour]; handler.WriteChar(hour.First); handler.WriteChar(hour.Second); handler.WriteChar(':'); } { var minute = DigitPairs[value.Minute]; handler.WriteChar(minute.First); handler.WriteChar(minute.Second); handler.WriteChar(':'); } { var second = DigitPairs[value.Second]; handler.WriteChar(second.First); handler.WriteChar(second.Second); } handler.WriteString(" GMT\""); } else if (handler.Option.DatetimeFormat == DatetimeFormatEnum.Microsoft) { /* * "\/Date(628318530718)\/" */ handler.WriteString("\"\\/Date("); handler.WriteLong((value.Ticks - 621355968000000000L) / 10000L); handler.WriteString(")\\/\""); } }