Guest User

Untitled

a guest
Jun 19th, 2018
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.96 KB | None | 0 0
  1. public class Rison
  2. {
  3. private string currentString;
  4. private int index = 0;
  5. private string next_id_rgx = @"[^-0123456789 '!:(),*@$][^ '!:(),*@$]*";
  6. private Dictionary<char, Func<object>> Table;
  7. private Dictionary<char, Func<Rison, object>> Bands = new Dictionary<char, Func<Rison, object>>()
  8. {
  9. { 't', (x) => { return true; } },
  10. { 'f', (x) => { return false; } },
  11. { 'n', (x) => { return null; } },
  12. { '(', (inst) => {
  13. var ar = new List<dynamic>();
  14. char c = '\0';
  15. while((c = inst.Next()) != ')')
  16. {
  17. if(c == '\0') throw new Exception("unmatched !");
  18. if(ar.Count > 0)
  19. {
  20. if(c != ',') throw new Exception("missin ,");
  21. } else if (c == ',')
  22. throw new Exception("extra ,");
  23. else
  24. --inst.index;
  25. var n = inst.ReadValue();
  26. if(n != null)
  27. {
  28. ar.Add(n);
  29. }
  30. }
  31. return ar;
  32. } }
  33. };
  34.  
  35. private Dictionary<char, Func<object>> GetTable()
  36. {
  37. return new Dictionary<char, Func<object>>()
  38. {
  39. { '!', ExclamationMark },
  40. { '(', Bracket },
  41. { '\'', Apostrophe },
  42. { '-', Dash }
  43. };
  44. }
  45.  
  46. private object ExclamationMark()
  47. {
  48. var result = new object();
  49. var s = currentString;
  50. var c = s[index++];
  51. if (c == '\0') throw new Exception("asdasd");
  52. if (Bands.TryGetValue(c, out Func<Rison, object> func))
  53. {
  54. if (c == '(')
  55. result = func.Invoke(this);
  56. else
  57. result = func.Invoke(null);
  58. }
  59. else
  60. {
  61. throw new Exception("unkown literal: !" + c);
  62. }
  63. return result;
  64. }
  65. private object Bracket()
  66. {
  67. var o = new Dictionary<string, object>();
  68. char c;
  69.  
  70. int count = 0;
  71. while ((c = Next()) != ')')
  72. {
  73. if (count > 0)
  74. {
  75. if (c != ',') throw new Exception("missing ,");
  76. }
  77. else if (c == ',')
  78. return new Exception("extra ,");
  79. else
  80. --index;
  81. var k = ReadValue();
  82. if (k == null) return null;
  83. if (Next() != ':') throw new Exception("missing :");
  84. var v = ReadValue();
  85. o.Add(k.ToString(), v);
  86. count++;
  87. }
  88. ExpandoObject obj = o.Expando();
  89. return obj;
  90. }
  91.  
  92. private object Apostrophe()
  93. {
  94. var s = currentString;
  95. var i = index;
  96. var start = i;
  97. var segments = new List<string>();
  98. char c = '\0';
  99. while ((c = s[i++]) != '\'')
  100. {
  101. if (c == '\0') throw new Exception("unmatched '");
  102. if (c == '!')
  103. {
  104. if (start < i - 1)
  105. segments.Add(s.Slice(start, i - 1));
  106. c = s[i++];
  107. if ("!'".Contains(c.ToString()))
  108. {
  109. segments.Add(c.ToString());
  110. }
  111. else
  112. {
  113. throw new Exception("invalid string escape: !");
  114. }
  115. start = i;
  116. }
  117. }
  118. if (start < i - 1)
  119. segments.Add(s.Slice(start, i - 1));
  120. index = i;
  121. return segments.Count == 1 ? segments[0] : string.Join("", segments);
  122. }
  123. private object Dash()
  124. {
  125. var s = currentString;
  126. var i = index;
  127. var start = i - 1;
  128. var permittedSigns = "-";
  129. var state = true;
  130. do
  131. {
  132. var c = s[i++];
  133. if (c == '\0') break;
  134. if (char.IsDigit(c))
  135. continue;
  136. if (permittedSigns.Contains(c.ToString()))
  137. {
  138. permittedSigns = "";
  139. continue;
  140. }
  141. state = false;
  142. } while (state);
  143. index = --i;
  144. s = s.Slice(start, i);
  145. if (s.Equals("-")) throw new Exception("invalid number");
  146. return s;
  147. }
  148.  
  149. public string Decode(string objectToDecode)
  150. {
  151. Table = GetTable();
  152. return Parse(objectToDecode);
  153. }
  154.  
  155. private string Parse(string obj)
  156. {
  157. currentString = obj;
  158. index = 0;
  159. return JsonConvert.SerializeObject(ReadValue());
  160. }
  161. private object ReadValue()
  162. {
  163. var nextChar = Next();
  164. var copiedNextChar = nextChar;
  165. if (char.IsDigit(nextChar))
  166. {
  167. copiedNextChar = '-';
  168. }
  169. if (Table.TryGetValue(copiedNextChar, out Func<object> fun))
  170. {
  171. var obj = fun.Invoke();
  172. return obj;
  173. }
  174.  
  175. var s = currentString;
  176. var i = index - 1;
  177. //remove from s from begin to i
  178. var removed = s.Remove(0, i);
  179. var matchedRgx = Regex.Match(removed, next_id_rgx);
  180. if (matchedRgx.Success)
  181. {
  182. var id = matchedRgx.Value;
  183. index = i + id.Length;
  184. return id;
  185. }
  186. if (nextChar != '\0')
  187. {
  188. throw new Exception("invalid character " + nextChar);
  189. }
  190. return string.Empty;
  191. }
  192.  
  193. private char Next()
  194. {
  195. char c = '\0';
  196. var s = currentString;
  197. var i = index;
  198. do
  199. {
  200. if (i == s.Length) return '\0';
  201. c = s[i++];
  202. } while ("".IndexOf(c) >= 0);
  203. index = i;
  204. return c;
  205. }
  206. }
  207.  
  208. public static class Extensions
  209. {
  210. public static string Slice(this string source, int start, int end)
  211. {
  212. if (end < 0)
  213. {
  214. end = source.Length + end;
  215. }
  216. int len = end - start;
  217. return source.Substring(start, len);
  218. }
  219.  
  220. public static ExpandoObject Expando(this IEnumerable<KeyValuePair<string, object>> dictionary)
  221. {
  222. var expando = new ExpandoObject();
  223. var expandoDic = (IDictionary<string, object>)expando;
  224. foreach (var item in dictionary)
  225. {
  226. expandoDic.Add(item);
  227. }
  228. return expando;
  229. }
  230. }
Add Comment
Please, Sign In to add comment