Advertisement
CGC_Codes

Formatter TinyJson

Feb 23rd, 2017
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 18.51 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Reflection;
  6. using System.Text;
  7.  
  8. // TinyJson is handmade Json reader/writer library.
  9. // It doesn't needs JSON.NET dependency.
  10.  
  11. namespace ZeroFormatter.Analyzer
  12. {
  13.     public class TinyJsonException : Exception
  14.     {
  15.         public TinyJsonException(string message) : base(message)
  16.         {
  17.  
  18.         }
  19.     }
  20.  
  21.     public class KnownTypeSerializer
  22.     {
  23.         readonly Dictionary<Type, Func<object, string>> serializers = new Dictionary<Type, Func<object, string>>();
  24.         readonly Dictionary<Type, Func<string, object>> deserializers = new Dictionary<Type, Func<string, object>>();
  25.  
  26.         public static KnownTypeSerializer Default = new KnownTypeSerializer();
  27.  
  28.         public KnownTypeSerializer()
  29.         {
  30.             serializers.Add(typeof(DateTime), x => ((DateTime)x).ToString("o"));
  31.             deserializers.Add(typeof(DateTime), x => DateTime.Parse(x));
  32.             serializers.Add(typeof(DateTimeOffset), x => ((DateTimeOffset)x).ToString("o"));
  33.             deserializers.Add(typeof(DateTimeOffset), x => DateTimeOffset.Parse(x));
  34.             serializers.Add(typeof(Uri), x => ((Uri)x).ToString());
  35.             deserializers.Add(typeof(Uri), x => new Uri(x));
  36.             serializers.Add(typeof(Guid), x => ((Guid)x).ToString());
  37.             deserializers.Add(typeof(Guid), x => new Guid(x));
  38.         }
  39.  
  40.         public bool Contains(Type type)
  41.         {
  42.             return serializers.ContainsKey(type);
  43.         }
  44.  
  45.         public void Register(Type type, Func<object, string> serializer, Func<string, object> deserializer)
  46.         {
  47.             serializers[type] = serializer;
  48.             deserializers[type] = deserializer;
  49.         }
  50.  
  51.         public bool TrySerialize(Type type, object obj, out string result)
  52.         {
  53.             Func<object, string> serializer;
  54.             if (type != null && serializers.TryGetValue(type, out serializer))
  55.             {
  56.                 result = serializer(obj);
  57.                 return true;
  58.             }
  59.             else
  60.             {
  61.                 result = null;
  62.                 return false;
  63.             }
  64.         }
  65.  
  66.         public bool TryDeserialize(Type type, string json, out object result)
  67.         {
  68.             Func<string, object> deserializer;
  69.             if (type != null && deserializers.TryGetValue(type, out deserializer))
  70.             {
  71.                 result = deserializer(json);
  72.                 return true;
  73.             }
  74.             else
  75.             {
  76.                 result = null;
  77.                 return false;
  78.             }
  79.         }
  80.     }
  81.  
  82.     public enum TinyJsonToken
  83.     {
  84.         None,
  85.         StartObject,  // {
  86.         EndObject,    // }
  87.         StartArray,   // [
  88.         EndArray,     // ]
  89.         Number,       // -0~9
  90.         String,       // "___"
  91.         True,         // true
  92.         False,        // false
  93.         Null,         // null
  94.     }
  95.  
  96.     public class TinyJsonReader : IDisposable
  97.     {
  98.         readonly TextReader reader;
  99.         readonly bool disposeInnerReader;
  100.  
  101.         public TinyJsonToken TokenType { get; private set; }
  102.         public object Value { get; private set; }
  103.  
  104.         public TinyJsonReader(TextReader reader, bool disposeInnerReader = true)
  105.         {
  106.             this.reader = reader;
  107.             this.disposeInnerReader = disposeInnerReader;
  108.         }
  109.  
  110.         public bool Read()
  111.         {
  112.             ReadNextToken();
  113.             ReadValue();
  114.             return TokenType != TinyJsonToken.None;
  115.         }
  116.  
  117.         public void Dispose()
  118.         {
  119.             if (reader != null && disposeInnerReader)
  120.             {
  121.                 reader.Dispose();
  122.             }
  123.             TokenType = TinyJsonToken.None;
  124.             Value = null;
  125.         }
  126.  
  127.         void SkipWhiteSpace()
  128.         {
  129.             var c = reader.Peek();
  130.             while (c != -1 && Char.IsWhiteSpace((char)c))
  131.             {
  132.                 reader.Read();
  133.                 c = reader.Peek();
  134.             }
  135.         }
  136.  
  137.         char ReadChar()
  138.         {
  139.             return (char)reader.Read();
  140.         }
  141.  
  142.         static bool IsWordBreak(char c)
  143.         {
  144.             switch (c)
  145.             {
  146.                 case ' ':
  147.                 case '{':
  148.                 case '}':
  149.                 case '[':
  150.                 case ']':
  151.                 case ',':
  152.                 case ':':
  153.                 case '\"':
  154.                     return true;
  155.                 default:
  156.                     return false;
  157.             }
  158.         }
  159.  
  160.         void ReadNextToken()
  161.         {
  162.             SkipWhiteSpace();
  163.  
  164.             var intChar = reader.Peek();
  165.             if (intChar == -1)
  166.             {
  167.                 TokenType = TinyJsonToken.None;
  168.                 return;
  169.             }
  170.  
  171.             var c = (char)intChar;
  172.             switch (c)
  173.             {
  174.                 case '{':
  175.                     TokenType = TinyJsonToken.StartObject;
  176.                     return;
  177.                 case '}':
  178.                     TokenType = TinyJsonToken.EndObject;
  179.                     return;
  180.                 case '[':
  181.                     TokenType = TinyJsonToken.StartArray;
  182.                     return;
  183.                 case ']':
  184.                     TokenType = TinyJsonToken.EndArray;
  185.                     return;
  186.                 case '"':
  187.                     TokenType = TinyJsonToken.String;
  188.                     return;
  189.                 case '0':
  190.                 case '1':
  191.                 case '2':
  192.                 case '3':
  193.                 case '4':
  194.                 case '5':
  195.                 case '6':
  196.                 case '7':
  197.                 case '8':
  198.                 case '9':
  199.                 case '-':
  200.                     TokenType = TinyJsonToken.Number;
  201.                     return;
  202.                 case 't':
  203.                     TokenType = TinyJsonToken.True;
  204.                     return;
  205.                 case 'f':
  206.                     TokenType = TinyJsonToken.False;
  207.                     return;
  208.                 case 'n':
  209.                     TokenType = TinyJsonToken.Null;
  210.                     return;
  211.                 case ',':
  212.                 case ':':
  213.                     reader.Read();
  214.                     ReadNextToken();
  215.                     return;
  216.                 default:
  217.                     throw new TinyJsonException("Invalid String:" + c);
  218.             }
  219.         }
  220.  
  221.         void ReadValue()
  222.         {
  223.             Value = null;
  224.  
  225.             switch (TokenType)
  226.             {
  227.                 case TinyJsonToken.None:
  228.                     break;
  229.                 case TinyJsonToken.StartObject:
  230.                 case TinyJsonToken.EndObject:
  231.                 case TinyJsonToken.StartArray:
  232.                 case TinyJsonToken.EndArray:
  233.                     reader.Read();
  234.                     break;
  235.                 case TinyJsonToken.Number:
  236.                     ReadNumber();
  237.                     break;
  238.                 case TinyJsonToken.String:
  239.                     ReadString();
  240.                     break;
  241.                 case TinyJsonToken.True:
  242.                     if (ReadChar() != 't') throw new TinyJsonException("Invalid Token");
  243.                     if (ReadChar() != 'r') throw new TinyJsonException("Invalid Token");
  244.                     if (ReadChar() != 'u') throw new TinyJsonException("Invalid Token");
  245.                     if (ReadChar() != 'e') throw new TinyJsonException("Invalid Token");
  246.                     Value = true;
  247.                     break;
  248.                 case TinyJsonToken.False:
  249.                     if (ReadChar() != 'f') throw new TinyJsonException("Invalid Token");
  250.                     if (ReadChar() != 'a') throw new TinyJsonException("Invalid Token");
  251.                     if (ReadChar() != 'l') throw new TinyJsonException("Invalid Token");
  252.                     if (ReadChar() != 's') throw new TinyJsonException("Invalid Token");
  253.                     if (ReadChar() != 'e') throw new TinyJsonException("Invalid Token");
  254.                     Value = false;
  255.                     break;
  256.                 case TinyJsonToken.Null:
  257.                     if (ReadChar() != 'n') throw new TinyJsonException("Invalid Token");
  258.                     if (ReadChar() != 'u') throw new TinyJsonException("Invalid Token");
  259.                     if (ReadChar() != 'l') throw new TinyJsonException("Invalid Token");
  260.                     if (ReadChar() != 'l') throw new TinyJsonException("Invalid Token");
  261.                     Value = null;
  262.                     break;
  263.                 default:
  264.                     throw new ArgumentException("InvalidTokenState:" + TokenType);
  265.             }
  266.         }
  267.  
  268.         void ReadNumber()
  269.         {
  270.             var numberWord = new StringBuilder();
  271.  
  272.             var isDouble = false;
  273.             var intChar = reader.Peek();
  274.             while (intChar != -1 && !IsWordBreak((char)intChar))
  275.             {
  276.                 var c = ReadChar();
  277.                 numberWord.Append(c);
  278.                 if (c == '.') isDouble = true;
  279.                 intChar = reader.Peek();
  280.             }
  281.  
  282.             var number = numberWord.ToString();
  283.             if (isDouble)
  284.             {
  285.                 double parsedDouble;
  286.                 Double.TryParse(number, out parsedDouble);
  287.                 Value = parsedDouble;
  288.             }
  289.             else
  290.             {
  291.                 long parsedInt;
  292.                 if (Int64.TryParse(number, out parsedInt))
  293.                 {
  294.                     Value = parsedInt;
  295.                     return;
  296.                 }
  297.  
  298.                 ulong parsedULong;
  299.                 if (ulong.TryParse(number, out parsedULong))
  300.                 {
  301.                     Value = parsedULong;
  302.                     return;
  303.                 }
  304.  
  305.                 Decimal parsedDecimal;
  306.                 if (decimal.TryParse(number, out parsedDecimal))
  307.                 {
  308.                     Value = parsedDecimal;
  309.                     return;
  310.                 }
  311.             }
  312.         }
  313.  
  314.         void ReadString()
  315.         {
  316.             reader.Read(); // skip ["]
  317.  
  318.             var sb = new StringBuilder();
  319.             while (true)
  320.             {
  321.                 if (reader.Peek() == -1) throw new TinyJsonException("Invalid Json String");
  322.  
  323.                 var c = ReadChar();
  324.                 switch (c)
  325.                 {
  326.                     case '"': // endtoken
  327.                         goto END;
  328.                     case '\\': // escape character
  329.                         if (reader.Peek() == -1) throw new TinyJsonException("Invalid Json String");
  330.  
  331.                         c = ReadChar();
  332.                         switch (c)
  333.                         {
  334.                             case '"':
  335.                             case '\\':
  336.                             case '/':
  337.                                 sb.Append(c);
  338.                                 break;
  339.                             case 'b':
  340.                                 sb.Append('\b');
  341.                                 break;
  342.                             case 'f':
  343.                                 sb.Append('\f');
  344.                                 break;
  345.                             case 'n':
  346.                                 sb.Append('\n');
  347.                                 break;
  348.                             case 'r':
  349.                                 sb.Append('\r');
  350.                                 break;
  351.                             case 't':
  352.                                 sb.Append('\t');
  353.                                 break;
  354.                             case 'u':
  355.                                 var hex = new char[4];
  356.                                 hex[0] = ReadChar();
  357.                                 hex[1] = ReadChar();
  358.                                 hex[2] = ReadChar();
  359.                                 hex[3] = ReadChar();
  360.                                 sb.Append((char)Convert.ToInt32(new string(hex), 16));
  361.                                 break;
  362.                         }
  363.                         break;
  364.                     default: // string
  365.                         sb.Append(c);
  366.                         break;
  367.                 }
  368.             }
  369.  
  370.         END:
  371.             Value = sb.ToString();
  372.         }
  373.     }
  374.  
  375.     public class TinyJsonWriter : IDisposable
  376.     {
  377.         enum WritingState
  378.         {
  379.             Value, ArrayStart, ObjectStart, Array, Object, ObjectPropertyName
  380.         }
  381.  
  382.         readonly TextWriter writer;
  383.         readonly Stack<WritingState> state;
  384.         readonly bool disposeInnerWriter;
  385.  
  386.         public TinyJsonWriter(TextWriter writer, bool disposeInnerWriter = true)
  387.         {
  388.             this.writer = writer;
  389.             this.disposeInnerWriter = disposeInnerWriter;
  390.             this.state = new Stack<WritingState>();
  391.             state.Push(WritingState.Value);
  392.         }
  393.  
  394.         public void WriteStartObject()
  395.         {
  396.             WritePrefix();
  397.             writer.Write('{');
  398.             state.Push(WritingState.ObjectStart);
  399.         }
  400.  
  401.         public void WriteEndObject()
  402.         {
  403.             writer.Write('}');
  404.             state.Pop();
  405.         }
  406.  
  407.         public void WriteStartArray()
  408.         {
  409.             WritePrefix();
  410.             writer.Write('[');
  411.             state.Push(WritingState.ArrayStart);
  412.         }
  413.  
  414.         public void WriteEndArray()
  415.         {
  416.             writer.Write(']');
  417.             state.Pop();
  418.         }
  419.  
  420.         public void WritePropertyName(string name)
  421.         {
  422.             WritePrefix();
  423.             state.Push(WritingState.ObjectPropertyName);
  424.             WriteString(name);
  425.         }
  426.  
  427.         public void WriteValue(object obj)
  428.         {
  429.             WriteValue(obj, KnownTypeSerializer.Default);
  430.         }
  431.  
  432.         public void WriteValue(object obj, KnownTypeSerializer serializer)
  433.         {
  434.             WritePrefix();
  435.  
  436.             // write value
  437.             if (obj == null)
  438.             {
  439.                 writer.Write("null");
  440.             }
  441.             else if (obj is string)
  442.             {
  443.                 WriteString((string)obj);
  444.             }
  445.             else if (obj is bool)
  446.             {
  447.                 writer.Write(((bool)obj) ? "true" : "false");
  448.             }
  449.             else
  450.             {
  451.                 var t = obj.GetType();
  452.                 if (t.GetTypeInfo().IsEnum)
  453.                 {
  454.                     var eValue = Convert.ChangeType(obj, Enum.GetUnderlyingType(t));
  455.                     writer.Write(eValue); // Enum as WriteNumber
  456.                     return;
  457.                 }
  458.  
  459.                 if (t == typeof(sbyte))
  460.                 {
  461.                     writer.Write((sbyte)obj);
  462.                 }
  463.                 else if (t == typeof(byte))
  464.                 {
  465.                     writer.Write((byte)obj);
  466.                 }
  467.                 else if (t == typeof(Int16))
  468.                 {
  469.                     writer.Write((Int16)obj);
  470.                 }
  471.                 else if (t == typeof(UInt16))
  472.                 {
  473.                     writer.Write((UInt16)obj);
  474.                 }
  475.                 else if (t == typeof(Int32))
  476.                 {
  477.                     writer.Write((Int32)obj);
  478.                 }
  479.                 else if (t == typeof(UInt32))
  480.                 {
  481.                     writer.Write((UInt32)obj);
  482.                 }
  483.                 else if (t == typeof(Int64))
  484.                 {
  485.                     writer.Write((Int64)obj);
  486.                 }
  487.                 else if (t == typeof(UInt64))
  488.                 {
  489.                     writer.Write((UInt64)obj);
  490.                 }
  491.                 else if (t == typeof(Single))
  492.                 {
  493.                     writer.Write((Single)obj);
  494.                 }
  495.                 else if (t == typeof(Double))
  496.                 {
  497.                     writer.Write((Double)obj);
  498.                 }
  499.                 else if (t == typeof(Decimal))
  500.                 {
  501.                     writer.Write((Decimal)obj);
  502.                 }
  503.                 else
  504.                 {
  505.                     string result;
  506.                     if (serializer.TrySerialize(t, obj, out result))
  507.                     {
  508.                         WriteString(result);
  509.                     }
  510.                     else
  511.                     {
  512.                         WriteString(obj.ToString());
  513.                     }
  514.                 }
  515.             }
  516.         }
  517.  
  518.         void WritePrefix()
  519.         {
  520.             // write prefix by state
  521.             var currentState = state.Peek();
  522.             switch (currentState)
  523.             {
  524.                 case WritingState.Value:
  525.                     break;
  526.                 case WritingState.ArrayStart:
  527.                     state.Pop();
  528.                     state.Push(WritingState.Array);
  529.                     break;
  530.                 case WritingState.ObjectStart:
  531.                     state.Pop();
  532.                     state.Push(WritingState.Object);
  533.                     break;
  534.                 case WritingState.Array:
  535.                 case WritingState.Object:
  536.                     writer.Write(',');
  537.                     break;
  538.                 case WritingState.ObjectPropertyName:
  539.                     state.Pop();
  540.                     writer.Write(':');
  541.                     break;
  542.                 default:
  543.                     break;
  544.             }
  545.         }
  546.  
  547.         void WriteString(string o)
  548.         {
  549.             writer.Write('\"');
  550.  
  551.             for (int i = 0; i < o.Length; i++)
  552.             {
  553.                 var c = o[i];
  554.                 switch (c)
  555.                 {
  556.                     case '"':
  557.                         writer.Write("\\\"");
  558.                         break;
  559.                     case '\\':
  560.                         writer.Write("\\\\");
  561.                         break;
  562.                     case '\b':
  563.                         writer.Write("\\b");
  564.                         break;
  565.                     case '\f':
  566.                         writer.Write("\\f");
  567.                         break;
  568.                     case '\n':
  569.                         writer.Write("\\n");
  570.                         break;
  571.                     case '\r':
  572.                         writer.Write("\\r");
  573.                         break;
  574.                     case '\t':
  575.                         writer.Write("\\t");
  576.                         break;
  577.                     default:
  578.                         writer.Write(c);
  579.                         break;
  580.                 }
  581.             }
  582.  
  583.             writer.Write('\"');
  584.         }
  585.  
  586.         public void Dispose()
  587.         {
  588.             if (writer != null && disposeInnerWriter)
  589.             {
  590.                 writer.Dispose();
  591.             }
  592.         }
  593.     }
  594. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement