Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fix starting with Quote bug

  • Loading branch information...
commit 7fcc505e287f4736b48857d642fadcfb488cd568 1 parent 2134272
Demis Bellot authored June 05, 2012
1,072  src/ServiceStack.Text/Json/JsonTypeSerializer.cs
@@ -18,113 +18,113 @@
18 18
 
19 19
 namespace ServiceStack.Text.Json
20 20
 {
21  
-	internal class JsonTypeSerializer
22  
-		: ITypeSerializer
23  
-	{
24  
-		public static ITypeSerializer Instance = new JsonTypeSerializer();
25  
-
26  
-		public string TypeAttrInObject { get { return "{\"__type\":"; } }
27  
-
28  
-		public static readonly bool[] WhiteSpaceFlags = new bool[(int)' ' + 1];
29  
-
30  
-		static JsonTypeSerializer()
31  
-		{
32  
-			WhiteSpaceFlags[(int)' '] = true;
33  
-			WhiteSpaceFlags[(int)'\t'] = true;
34  
-			WhiteSpaceFlags[(int)'\r'] = true;
35  
-			WhiteSpaceFlags[(int)'\n'] = true;
36  
-		}
37  
-
38  
-		public WriteObjectDelegate GetWriteFn<T>()
39  
-		{
40  
-			return JsonWriter<T>.WriteFn();
41  
-		}
42  
-
43  
-		public WriteObjectDelegate GetWriteFn(Type type)
44  
-		{
45  
-			return JsonWriter.GetWriteFn(type);
46  
-		}
47  
-
48  
-		public TypeInfo GetTypeInfo(Type type)
49  
-		{
50  
-			return JsonWriter.GetTypeInfo(type);
51  
-		}
52  
-
53  
-		/// <summary>
54  
-		/// Shortcut escape when we're sure value doesn't contain any escaped chars
55  
-		/// </summary>
56  
-		/// <param name="writer"></param>
57  
-		/// <param name="value"></param>
58  
-		public void WriteRawString(TextWriter writer, string value)
59  
-		{
60  
-			writer.Write(JsWriter.QuoteChar);
61  
-			writer.Write(value);
62  
-			writer.Write(JsWriter.QuoteChar);
63  
-		}
64  
-
65  
-		public void WritePropertyName(TextWriter writer, string value)
66  
-		{
67  
-			if (JsState.WritingKeyCount > 0)
68  
-			{
69  
-				writer.Write(JsWriter.EscapedQuoteString);
70  
-				writer.Write(value);
71  
-				writer.Write(JsWriter.EscapedQuoteString);
72  
-			}
73  
-			else
74  
-			{
75  
-				WriteRawString(writer, value);
76  
-			}
77  
-		}
78  
-
79  
-		public void WriteString(TextWriter writer, string value)
80  
-		{
81  
-			JsonUtils.WriteString(writer, value);
82  
-		}
83  
-
84  
-		public void WriteBuiltIn(TextWriter writer, object value)
85  
-		{
86  
-			if (JsState.WritingKeyCount > 0 && !JsState.IsWritingValue) writer.Write(JsonUtils.QuoteChar);
87  
-
88  
-			WriteRawString(writer, value.ToString());
89  
-
90  
-			if (JsState.WritingKeyCount > 0 && !JsState.IsWritingValue) writer.Write(JsonUtils.QuoteChar);
91  
-		}
92  
-
93  
-		public void WriteObjectString(TextWriter writer, object value)
94  
-		{
95  
-			JsonUtils.WriteString(writer, value != null ? value.ToString() : null);
96  
-		}
97  
-
98  
-		public void WriteException(TextWriter writer, object value)
99  
-		{
100  
-			WriteString(writer, ((Exception)value).Message);
101  
-		}
102  
-
103  
-		public void WriteDateTime(TextWriter writer, object oDateTime)
104  
-		{
105  
-			WriteRawString(writer, DateTimeSerializer.ToWcfJsonDate((DateTime)oDateTime));
106  
-		}
107  
-
108  
-		public void WriteNullableDateTime(TextWriter writer, object dateTime)
109  
-		{
110  
-			if (dateTime == null)
111  
-				writer.Write( JsonUtils.Null );
112  
-			else
113  
-				WriteDateTime(writer, dateTime);
114  
-		}
115  
-
116  
-		public void WriteDateTimeOffset(TextWriter writer, object oDateTimeOffset)
117  
-		{
118  
-			WriteRawString(writer, DateTimeSerializer.ToWcfJsonDateTimeOffset((DateTimeOffset)oDateTimeOffset));
119  
-		}
120  
-
121  
-		public void WriteNullableDateTimeOffset(TextWriter writer, object dateTimeOffset)
122  
-		{
123  
-			if (dateTimeOffset == null)
124  
-				writer.Write(JsonUtils.Null);
125  
-			else
126  
-				WriteDateTimeOffset(writer, dateTimeOffset);
127  
-		}
  21
+    internal class JsonTypeSerializer
  22
+        : ITypeSerializer
  23
+    {
  24
+        public static ITypeSerializer Instance = new JsonTypeSerializer();
  25
+
  26
+        public string TypeAttrInObject { get { return "{\"__type\":"; } }
  27
+
  28
+        public static readonly bool[] WhiteSpaceFlags = new bool[(int)' ' + 1];
  29
+
  30
+        static JsonTypeSerializer()
  31
+        {
  32
+            WhiteSpaceFlags[(int)' '] = true;
  33
+            WhiteSpaceFlags[(int)'\t'] = true;
  34
+            WhiteSpaceFlags[(int)'\r'] = true;
  35
+            WhiteSpaceFlags[(int)'\n'] = true;
  36
+        }
  37
+
  38
+        public WriteObjectDelegate GetWriteFn<T>()
  39
+        {
  40
+            return JsonWriter<T>.WriteFn();
  41
+        }
  42
+
  43
+        public WriteObjectDelegate GetWriteFn(Type type)
  44
+        {
  45
+            return JsonWriter.GetWriteFn(type);
  46
+        }
  47
+
  48
+        public TypeInfo GetTypeInfo(Type type)
  49
+        {
  50
+            return JsonWriter.GetTypeInfo(type);
  51
+        }
  52
+
  53
+        /// <summary>
  54
+        /// Shortcut escape when we're sure value doesn't contain any escaped chars
  55
+        /// </summary>
  56
+        /// <param name="writer"></param>
  57
+        /// <param name="value"></param>
  58
+        public void WriteRawString(TextWriter writer, string value)
  59
+        {
  60
+            writer.Write(JsWriter.QuoteChar);
  61
+            writer.Write(value);
  62
+            writer.Write(JsWriter.QuoteChar);
  63
+        }
  64
+
  65
+        public void WritePropertyName(TextWriter writer, string value)
  66
+        {
  67
+            if (JsState.WritingKeyCount > 0)
  68
+            {
  69
+                writer.Write(JsWriter.EscapedQuoteString);
  70
+                writer.Write(value);
  71
+                writer.Write(JsWriter.EscapedQuoteString);
  72
+            }
  73
+            else
  74
+            {
  75
+                WriteRawString(writer, value);
  76
+            }
  77
+        }
  78
+
  79
+        public void WriteString(TextWriter writer, string value)
  80
+        {
  81
+            JsonUtils.WriteString(writer, value);
  82
+        }
  83
+
  84
+        public void WriteBuiltIn(TextWriter writer, object value)
  85
+        {
  86
+            if (JsState.WritingKeyCount > 0 && !JsState.IsWritingValue) writer.Write(JsonUtils.QuoteChar);
  87
+
  88
+            WriteRawString(writer, value.ToString());
  89
+
  90
+            if (JsState.WritingKeyCount > 0 && !JsState.IsWritingValue) writer.Write(JsonUtils.QuoteChar);
  91
+        }
  92
+
  93
+        public void WriteObjectString(TextWriter writer, object value)
  94
+        {
  95
+            JsonUtils.WriteString(writer, value != null ? value.ToString() : null);
  96
+        }
  97
+
  98
+        public void WriteException(TextWriter writer, object value)
  99
+        {
  100
+            WriteString(writer, ((Exception)value).Message);
  101
+        }
  102
+
  103
+        public void WriteDateTime(TextWriter writer, object oDateTime)
  104
+        {
  105
+            WriteRawString(writer, DateTimeSerializer.ToWcfJsonDate((DateTime)oDateTime));
  106
+        }
  107
+
  108
+        public void WriteNullableDateTime(TextWriter writer, object dateTime)
  109
+        {
  110
+            if (dateTime == null)
  111
+                writer.Write(JsonUtils.Null);
  112
+            else
  113
+                WriteDateTime(writer, dateTime);
  114
+        }
  115
+
  116
+        public void WriteDateTimeOffset(TextWriter writer, object oDateTimeOffset)
  117
+        {
  118
+            WriteRawString(writer, DateTimeSerializer.ToWcfJsonDateTimeOffset((DateTimeOffset)oDateTimeOffset));
  119
+        }
  120
+
  121
+        public void WriteNullableDateTimeOffset(TextWriter writer, object dateTimeOffset)
  122
+        {
  123
+            if (dateTimeOffset == null)
  124
+                writer.Write(JsonUtils.Null);
  125
+            else
  126
+                WriteDateTimeOffset(writer, dateTimeOffset);
  127
+        }
128 128
 
129 129
         public void WriteTimeSpan(TextWriter writer, object oTimeSpan)
130 130
         {
@@ -137,437 +137,437 @@ public void WriteNullableTimeSpan(TextWriter writer, object oTimeSpan)
137 137
             writer.Write(DateTimeSerializer.ToXsdTimeSpanString((TimeSpan?)oTimeSpan));
138 138
         }
139 139
 
140  
-		public void WriteGuid(TextWriter writer, object oValue)
141  
-		{
142  
-			WriteRawString(writer, ((Guid)oValue).ToString("N"));
143  
-		}
144  
-
145  
-		public void WriteNullableGuid(TextWriter writer, object oValue)
146  
-		{
147  
-			if (oValue == null) return;
148  
-			WriteRawString(writer, ((Guid)oValue).ToString("N"));
149  
-		}
150  
-
151  
-		public void WriteBytes(TextWriter writer, object oByteValue)
152  
-		{
153  
-			if (oByteValue == null) return;
154  
-			WriteRawString(writer, Convert.ToBase64String((byte[])oByteValue));
155  
-		}
156  
-
157  
-		public void WriteChar(TextWriter writer, object charValue)
158  
-		{
159  
-			if (charValue == null)
160  
-				writer.Write(JsonUtils.Null);
161  
-			else
162  
-				WriteRawString(writer, ((char)charValue).ToString(CultureInfo.InvariantCulture));
163  
-		}
164  
-
165  
-		public void WriteByte(TextWriter writer, object byteValue)
166  
-		{
167  
-			if (byteValue == null)
168  
-				writer.Write(JsonUtils.Null);
169  
-			else
170  
-				writer.Write((byte)byteValue);
171  
-		}
172  
-
173  
-		public void WriteInt16(TextWriter writer, object intValue)
174  
-		{
175  
-			if (intValue == null)
176  
-				writer.Write(JsonUtils.Null);
177  
-			else
178  
-				writer.Write((short)intValue);
179  
-		}
180  
-
181  
-		public void WriteUInt16(TextWriter writer, object intValue)
182  
-		{
183  
-			if (intValue == null)
184  
-				writer.Write(JsonUtils.Null);
185  
-			else
186  
-				writer.Write((ushort)intValue);
187  
-		}
188  
-
189  
-		public void WriteInt32(TextWriter writer, object intValue)
190  
-		{
191  
-			if (intValue == null)
192  
-				writer.Write(JsonUtils.Null);
193  
-			else
194  
-				writer.Write((int)intValue);
195  
-		}
196  
-
197  
-		public void WriteUInt32(TextWriter writer, object uintValue)
198  
-		{
199  
-			if (uintValue == null)
200  
-				writer.Write(JsonUtils.Null);
201  
-			else
202  
-				writer.Write((uint)uintValue);
203  
-		}
204  
-
205  
-		public void WriteInt64(TextWriter writer, object integerValue)
206  
-		{
207  
-			if (integerValue == null)
208  
-				writer.Write(JsonUtils.Null);
209  
-			else
210  
-				writer.Write((long)integerValue);
211  
-		}
212  
-
213  
-		public void WriteUInt64(TextWriter writer, object ulongValue)
214  
-		{
215  
-			if (ulongValue == null)
216  
-			{
217  
-				writer.Write(JsonUtils.Null);
218  
-			}
219  
-			else
220  
-				writer.Write((ulong)ulongValue);
221  
-		}
222  
-
223  
-		public void WriteBool(TextWriter writer, object boolValue)
224  
-		{
225  
-			if (boolValue == null)
226  
-				writer.Write(JsonUtils.Null);
227  
-			else
228  
-				writer.Write(((bool)boolValue) ? JsonUtils.True : JsonUtils.False);
229  
-		}
230  
-
231  
-		public void WriteFloat(TextWriter writer, object floatValue)
232  
-		{
233  
-			if (floatValue == null)
234  
-				writer.Write(JsonUtils.Null);
235  
-			else
236  
-			{
237  
-				var floatVal = (float)floatValue;
238  
-				if (Equals(floatVal, float.MaxValue) || Equals(floatVal, float.MinValue))
239  
-					writer.Write(floatVal.ToString("r", CultureInfo.InvariantCulture));
240  
-				else
241  
-					writer.Write(floatVal.ToString(CultureInfo.InvariantCulture));
242  
-			}
243  
-		}
244  
-
245  
-		public void WriteDouble(TextWriter writer, object doubleValue)
246  
-		{
247  
-			if (doubleValue == null)
248  
-				writer.Write(JsonUtils.Null);
249  
-			else
250  
-			{
251  
-				var doubleVal = (double)doubleValue;
252  
-				if (Equals(doubleVal, double.MaxValue) || Equals(doubleVal, double.MinValue))
253  
-					writer.Write(doubleVal.ToString("r", CultureInfo.InvariantCulture));
254  
-				else
255  
-					writer.Write(doubleVal.ToString(CultureInfo.InvariantCulture));
256  
-			}
257  
-		}
258  
-
259  
-		public void WriteDecimal(TextWriter writer, object decimalValue)
260  
-		{
261  
-			if (decimalValue == null)
262  
-				writer.Write(JsonUtils.Null);
263  
-			else
264  
-				writer.Write(((decimal)decimalValue).ToString(CultureInfo.InvariantCulture));
265  
-		}
266  
-
267  
-		public void WriteEnum(TextWriter writer, object enumValue)
268  
-		{
269  
-			if (enumValue == null) return;
270  
-			WriteRawString(writer, enumValue.ToString());
271  
-		}
272  
-
273  
-		public void WriteEnumFlags(TextWriter writer, object enumFlagValue)
274  
-		{
275  
-			if (enumFlagValue == null) return;
276  
-			var intVal = (int)enumFlagValue;
277  
-			writer.Write(intVal);
278  
-		}
279  
-
280  
-		public void WriteLinqBinary(TextWriter writer, object linqBinaryValue)
281  
-		{
  140
+        public void WriteGuid(TextWriter writer, object oValue)
  141
+        {
  142
+            WriteRawString(writer, ((Guid)oValue).ToString("N"));
  143
+        }
  144
+
  145
+        public void WriteNullableGuid(TextWriter writer, object oValue)
  146
+        {
  147
+            if (oValue == null) return;
  148
+            WriteRawString(writer, ((Guid)oValue).ToString("N"));
  149
+        }
  150
+
  151
+        public void WriteBytes(TextWriter writer, object oByteValue)
  152
+        {
  153
+            if (oByteValue == null) return;
  154
+            WriteRawString(writer, Convert.ToBase64String((byte[])oByteValue));
  155
+        }
  156
+
  157
+        public void WriteChar(TextWriter writer, object charValue)
  158
+        {
  159
+            if (charValue == null)
  160
+                writer.Write(JsonUtils.Null);
  161
+            else
  162
+                WriteRawString(writer, ((char)charValue).ToString(CultureInfo.InvariantCulture));
  163
+        }
  164
+
  165
+        public void WriteByte(TextWriter writer, object byteValue)
  166
+        {
  167
+            if (byteValue == null)
  168
+                writer.Write(JsonUtils.Null);
  169
+            else
  170
+                writer.Write((byte)byteValue);
  171
+        }
  172
+
  173
+        public void WriteInt16(TextWriter writer, object intValue)
  174
+        {
  175
+            if (intValue == null)
  176
+                writer.Write(JsonUtils.Null);
  177
+            else
  178
+                writer.Write((short)intValue);
  179
+        }
  180
+
  181
+        public void WriteUInt16(TextWriter writer, object intValue)
  182
+        {
  183
+            if (intValue == null)
  184
+                writer.Write(JsonUtils.Null);
  185
+            else
  186
+                writer.Write((ushort)intValue);
  187
+        }
  188
+
  189
+        public void WriteInt32(TextWriter writer, object intValue)
  190
+        {
  191
+            if (intValue == null)
  192
+                writer.Write(JsonUtils.Null);
  193
+            else
  194
+                writer.Write((int)intValue);
  195
+        }
  196
+
  197
+        public void WriteUInt32(TextWriter writer, object uintValue)
  198
+        {
  199
+            if (uintValue == null)
  200
+                writer.Write(JsonUtils.Null);
  201
+            else
  202
+                writer.Write((uint)uintValue);
  203
+        }
  204
+
  205
+        public void WriteInt64(TextWriter writer, object integerValue)
  206
+        {
  207
+            if (integerValue == null)
  208
+                writer.Write(JsonUtils.Null);
  209
+            else
  210
+                writer.Write((long)integerValue);
  211
+        }
  212
+
  213
+        public void WriteUInt64(TextWriter writer, object ulongValue)
  214
+        {
  215
+            if (ulongValue == null)
  216
+            {
  217
+                writer.Write(JsonUtils.Null);
  218
+            }
  219
+            else
  220
+                writer.Write((ulong)ulongValue);
  221
+        }
  222
+
  223
+        public void WriteBool(TextWriter writer, object boolValue)
  224
+        {
  225
+            if (boolValue == null)
  226
+                writer.Write(JsonUtils.Null);
  227
+            else
  228
+                writer.Write(((bool)boolValue) ? JsonUtils.True : JsonUtils.False);
  229
+        }
  230
+
  231
+        public void WriteFloat(TextWriter writer, object floatValue)
  232
+        {
  233
+            if (floatValue == null)
  234
+                writer.Write(JsonUtils.Null);
  235
+            else
  236
+            {
  237
+                var floatVal = (float)floatValue;
  238
+                if (Equals(floatVal, float.MaxValue) || Equals(floatVal, float.MinValue))
  239
+                    writer.Write(floatVal.ToString("r", CultureInfo.InvariantCulture));
  240
+                else
  241
+                    writer.Write(floatVal.ToString(CultureInfo.InvariantCulture));
  242
+            }
  243
+        }
  244
+
  245
+        public void WriteDouble(TextWriter writer, object doubleValue)
  246
+        {
  247
+            if (doubleValue == null)
  248
+                writer.Write(JsonUtils.Null);
  249
+            else
  250
+            {
  251
+                var doubleVal = (double)doubleValue;
  252
+                if (Equals(doubleVal, double.MaxValue) || Equals(doubleVal, double.MinValue))
  253
+                    writer.Write(doubleVal.ToString("r", CultureInfo.InvariantCulture));
  254
+                else
  255
+                    writer.Write(doubleVal.ToString(CultureInfo.InvariantCulture));
  256
+            }
  257
+        }
  258
+
  259
+        public void WriteDecimal(TextWriter writer, object decimalValue)
  260
+        {
  261
+            if (decimalValue == null)
  262
+                writer.Write(JsonUtils.Null);
  263
+            else
  264
+                writer.Write(((decimal)decimalValue).ToString(CultureInfo.InvariantCulture));
  265
+        }
  266
+
  267
+        public void WriteEnum(TextWriter writer, object enumValue)
  268
+        {
  269
+            if (enumValue == null) return;
  270
+            WriteRawString(writer, enumValue.ToString());
  271
+        }
  272
+
  273
+        public void WriteEnumFlags(TextWriter writer, object enumFlagValue)
  274
+        {
  275
+            if (enumFlagValue == null) return;
  276
+            var intVal = (int)enumFlagValue;
  277
+            writer.Write(intVal);
  278
+        }
  279
+
  280
+        public void WriteLinqBinary(TextWriter writer, object linqBinaryValue)
  281
+        {
282 282
 #if !MONOTOUCH && !SILVERLIGHT && !XBOX
283  
-			WriteRawString(writer, Convert.ToBase64String(((System.Data.Linq.Binary)linqBinaryValue).ToArray()));
  283
+            WriteRawString(writer, Convert.ToBase64String(((System.Data.Linq.Binary)linqBinaryValue).ToArray()));
284 284
 #endif
285  
-		}
286  
-
287  
-		public ParseStringDelegate GetParseFn<T>()
288  
-		{
289  
-			return JsonReader.Instance.GetParseFn<T>();
290  
-		}
291  
-
292  
-		public ParseStringDelegate GetParseFn(Type type)
293  
-		{
294  
-			return JsonReader.GetParseFn(type);
295  
-		}
296  
-
297  
-		public string ParseRawString(string value)
298  
-		{
299  
-			if (String.IsNullOrEmpty(value)) return value;
300  
-
301  
-			return value[0] == JsonUtils.QuoteChar
302  
-				? value.Substring(1, value.Length - 2)
303  
-				: value;
304  
-		}
305  
-
306  
-		public string ParseString(string value)
307  
-		{
308  
-			return string.IsNullOrEmpty(value) ? value : ParseRawString(value);
309  
-		}
310  
-
311  
-		static readonly char[] IsSafeJsonChars = new[] { JsonUtils.QuoteChar, JsonUtils.EscapeChar };
312  
-
313  
-		internal static string ParseJsonString(string json, ref int index)
314  
-		{
315  
-			var jsonLength = json.Length;
316  
-
317  
-			for (; index < json.Length; index++) { var ch = json[index]; if (ch >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[ch]) break; } //Whitespace inline
318  
-
319  
-			if (json[index] == JsonUtils.QuoteChar)
320  
-			{
321  
-				index++;
322  
-
323  
-				//MicroOp: See if we can short-circuit evaluation (to avoid StringBuilder)
324  
-				var strEndPos = json.IndexOfAny(IsSafeJsonChars, index);
325  
-				if (strEndPos == -1) return json.Substring(index, jsonLength - index);
326  
-				if (json[strEndPos] == JsonUtils.QuoteChar)
327  
-				{
328  
-					var potentialValue = json.Substring(index, strEndPos - index);
329  
-					index = strEndPos + 1;
330  
-					return potentialValue;
331  
-				}
332  
-			}
333  
-
334  
-			var sb = new StringBuilder(jsonLength);
335  
-			char c;
336  
-
337  
-			while (true)
338  
-			{
339  
-				if (index == jsonLength) break;
340  
-
341  
-				c = json[index++];
342  
-				if (c == JsonUtils.QuoteChar) break;
343  
-
344  
-				if (c == '\\')
345  
-				{
346  
-
347  
-					if (index == jsonLength)
348  
-					{
349  
-						break;
350  
-					}
351  
-					c = json[index++];
352  
-					switch (c)
353  
-					{
354  
-						case '"':
355  
-							sb.Append('"');
356  
-							break;
357  
-						case '\\':
358  
-							sb.Append('\\');
359  
-							break;
360  
-						case '/':
361  
-							sb.Append('/');
362  
-							break;
363  
-						case 'b':
364  
-							sb.Append('\b');
365  
-							break;
366  
-						case 'f':
367  
-							sb.Append('\f');
368  
-							break;
369  
-						case 'n':
370  
-							sb.Append('\n');
371  
-							break;
372  
-						case 'r':
373  
-							sb.Append('\r');
374  
-							break;
375  
-						case 't':
376  
-							sb.Append('\t');
377  
-							break;
378  
-						case 'u':
379  
-							var remainingLength = jsonLength - index;
380  
-							if (remainingLength >= 4)
381  
-							{
382  
-								var unicodeString = json.Substring(index, 4);
383  
-								var unicodeIntVal = UInt32.Parse(unicodeString, NumberStyles.HexNumber);
384  
-								sb.Append(ConvertFromUtf32((int)unicodeIntVal));
385  
-								index += 4;
386  
-							}
387  
-							else
388  
-							{
389  
-								break;
390  
-							}
391  
-							break;
392  
-					}
393  
-				}
394  
-				else
395  
-				{
396  
-					sb.Append(c);
397  
-				}
398  
-			}
399  
-
400  
-			var strValue = sb.ToString();
401  
-			return strValue == JsonUtils.Null ? null : strValue;
402  
-		}
403  
-
404  
-		/// <summary>
405  
-		/// Since Silverlight doesn't have char.ConvertFromUtf32() so putting Mono's implemenation inline.
406  
-		/// </summary>
407  
-		/// <param name="utf32"></param>
408  
-		/// <returns></returns>
409  
-		private static string ConvertFromUtf32(int utf32)
410  
-		{
411  
-			if (utf32 < 0 || utf32 > 0x10FFFF)
412  
-				throw new ArgumentOutOfRangeException("utf32", "The argument must be from 0 to 0x10FFFF.");
413  
-			if (0xD800 <= utf32 && utf32 <= 0xDFFF)
414  
-				throw new ArgumentOutOfRangeException("utf32", "The argument must not be in surrogate pair range.");
415  
-			if (utf32 < 0x10000)
416  
-				return new string((char)utf32, 1);
417  
-			utf32 -= 0x10000;
418  
-			return new string(new[] {(char) ((utf32 >> 10) + 0xD800),
  285
+        }
  286
+
  287
+        public ParseStringDelegate GetParseFn<T>()
  288
+        {
  289
+            return JsonReader.Instance.GetParseFn<T>();
  290
+        }
  291
+
  292
+        public ParseStringDelegate GetParseFn(Type type)
  293
+        {
  294
+            return JsonReader.GetParseFn(type);
  295
+        }
  296
+
  297
+        public string ParseRawString(string value)
  298
+        {
  299
+            if (String.IsNullOrEmpty(value)) return value;
  300
+
  301
+            return value[0] == JsonUtils.QuoteChar && value[value.Length - 1] == JsonUtils.QuoteChar
  302
+                ? value.Substring(1, value.Length - 2)
  303
+                : value;
  304
+        }
  305
+
  306
+        public string ParseString(string value)
  307
+        {
  308
+            return string.IsNullOrEmpty(value) ? value : ParseRawString(value);
  309
+        }
  310
+
  311
+        static readonly char[] IsSafeJsonChars = new[] { JsonUtils.QuoteChar, JsonUtils.EscapeChar };
  312
+
  313
+        internal static string ParseJsonString(string json, ref int index)
  314
+        {
  315
+            var jsonLength = json.Length;
  316
+
  317
+            for (; index < json.Length; index++) { var ch = json[index]; if (ch >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[ch]) break; } //Whitespace inline
  318
+
  319
+            if (json[index] == JsonUtils.QuoteChar)
  320
+            {
  321
+                index++;
  322
+
  323
+                //MicroOp: See if we can short-circuit evaluation (to avoid StringBuilder)
  324
+                var strEndPos = json.IndexOfAny(IsSafeJsonChars, index);
  325
+                if (strEndPos == -1) return json.Substring(index, jsonLength - index);
  326
+                if (json[strEndPos] == JsonUtils.QuoteChar)
  327
+                {
  328
+                    var potentialValue = json.Substring(index, strEndPos - index);
  329
+                    index = strEndPos + 1;
  330
+                    return potentialValue;
  331
+                }
  332
+            }
  333
+
  334
+            var sb = new StringBuilder(jsonLength);
  335
+            char c;
  336
+
  337
+            while (true)
  338
+            {
  339
+                if (index == jsonLength) break;
  340
+
  341
+                c = json[index++];
  342
+                if (c == JsonUtils.QuoteChar) break;
  343
+
  344
+                if (c == '\\')
  345
+                {
  346
+
  347
+                    if (index == jsonLength)
  348
+                    {
  349
+                        break;
  350
+                    }
  351
+                    c = json[index++];
  352
+                    switch (c)
  353
+                    {
  354
+                        case '"':
  355
+                            sb.Append('"');
  356
+                            break;
  357
+                        case '\\':
  358
+                            sb.Append('\\');
  359
+                            break;
  360
+                        case '/':
  361
+                            sb.Append('/');
  362
+                            break;
  363
+                        case 'b':
  364
+                            sb.Append('\b');
  365
+                            break;
  366
+                        case 'f':
  367
+                            sb.Append('\f');
  368
+                            break;
  369
+                        case 'n':
  370
+                            sb.Append('\n');
  371
+                            break;
  372
+                        case 'r':
  373
+                            sb.Append('\r');
  374
+                            break;
  375
+                        case 't':
  376
+                            sb.Append('\t');
  377
+                            break;
  378
+                        case 'u':
  379
+                            var remainingLength = jsonLength - index;
  380
+                            if (remainingLength >= 4)
  381
+                            {
  382
+                                var unicodeString = json.Substring(index, 4);
  383
+                                var unicodeIntVal = UInt32.Parse(unicodeString, NumberStyles.HexNumber);
  384
+                                sb.Append(ConvertFromUtf32((int)unicodeIntVal));
  385
+                                index += 4;
  386
+                            }
  387
+                            else
  388
+                            {
  389
+                                break;
  390
+                            }
  391
+                            break;
  392
+                    }
  393
+                }
  394
+                else
  395
+                {
  396
+                    sb.Append(c);
  397
+                }
  398
+            }
  399
+
  400
+            var strValue = sb.ToString();
  401
+            return strValue == JsonUtils.Null ? null : strValue;
  402
+        }
  403
+
  404
+        /// <summary>
  405
+        /// Since Silverlight doesn't have char.ConvertFromUtf32() so putting Mono's implemenation inline.
  406
+        /// </summary>
  407
+        /// <param name="utf32"></param>
  408
+        /// <returns></returns>
  409
+        private static string ConvertFromUtf32(int utf32)
  410
+        {
  411
+            if (utf32 < 0 || utf32 > 0x10FFFF)
  412
+                throw new ArgumentOutOfRangeException("utf32", "The argument must be from 0 to 0x10FFFF.");
  413
+            if (0xD800 <= utf32 && utf32 <= 0xDFFF)
  414
+                throw new ArgumentOutOfRangeException("utf32", "The argument must not be in surrogate pair range.");
  415
+            if (utf32 < 0x10000)
  416
+                return new string((char)utf32, 1);
  417
+            utf32 -= 0x10000;
  418
+            return new string(new[] {(char) ((utf32 >> 10) + 0xD800),
419 419
                                 (char) (utf32 % 0x0400 + 0xDC00)});
420  
-		}
421  
-
422  
-		private static void EatWhitespace(string json, ref int index)
423  
-		{
424  
-			int c;
425  
-			for (; index < json.Length; index++)
426  
-			{
427  
-				c = json[index];
428  
-				if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c])
429  
-				{
430  
-					break;
431  
-				}
432  
-			}
433  
-		}
434  
-
435  
-		public string EatTypeValue(string value, ref int i)
436  
-		{
437  
-			return EatValue(value, ref i);
438  
-		}
439  
-
440  
-		public bool EatMapStartChar(string value, ref int i)
441  
-		{
442  
-			for (; i < value.Length; i++) { var c = value[i]; if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c]) break; } //Whitespace inline
443  
-			return value[i++] == JsWriter.MapStartChar;
444  
-		}
445  
-
446  
-		public string EatMapKey(string value, ref int i)
447  
-		{
448  
-			return ParseJsonString(value, ref i);
449  
-		}
450  
-
451  
-		public bool EatMapKeySeperator(string value, ref int i)
452  
-		{
453  
-			for (; i < value.Length; i++) { var c = value[i]; if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c]) break; } //Whitespace inline
454  
-			if (value.Length == i) return false;
455  
-			return value[i++] == JsWriter.MapKeySeperator;
456  
-		}
457  
-
458  
-		public bool EatItemSeperatorOrMapEndChar(string value, ref int i)
459  
-		{
460  
-			for (; i < value.Length; i++) { var c = value[i]; if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c]) break; } //Whitespace inline
461  
-
462  
-			if (i == value.Length) return false;
463  
-
464  
-			var success = value[i] == JsWriter.ItemSeperator
465  
-				|| value[i] == JsWriter.MapEndChar;
466  
-
467  
-			i++;
468  
-
469  
-			if (success)
470  
-			{
471  
-				for (; i < value.Length; i++) { var c = value[i]; if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c]) break; } //Whitespace inline
472  
-			}
473  
-
474  
-			return success;
475  
-		}
476  
-
477  
-		public string EatValue(string value, ref int i)
478  
-		{
479  
-			var valueLength = value.Length;
480  
-			if (i == valueLength) return null;
481  
-
482  
-			for (; i < value.Length; i++) { var c = value[i]; if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c]) break; } //Whitespace inline
483  
-
484  
-			var tokenStartPos = i;
485  
-			var valueChar = value[i];
486  
-			var withinQuotes = false;
487  
-			var endsToEat = 1;
488  
-
489  
-			switch (valueChar)
490  
-			{
491  
-				//If we are at the end, return.
492  
-				case JsWriter.ItemSeperator:
493  
-				case JsWriter.MapEndChar:
494  
-					return null;
495  
-
496  
-				//Is Within Quotes, i.e. "..."
497  
-				case JsWriter.QuoteChar:
498  
-					return ParseJsonString(value, ref i);
499  
-
500  
-				//Is Type/Map, i.e. {...}
501  
-				case JsWriter.MapStartChar:
502  
-					while (++i < valueLength && endsToEat > 0)
503  
-					{
504  
-						valueChar = value[i];
505  
-
506  
-						if (valueChar == JsonUtils.EscapeChar)
507  
-						{
508  
-							i++;
509  
-							continue;
510  
-						}
511  
-
512  
-						if (valueChar == JsWriter.QuoteChar)
513  
-							withinQuotes = !withinQuotes;
514  
-
515  
-						if (withinQuotes)
516  
-							continue;
517  
-
518  
-						if (valueChar == JsWriter.MapStartChar)
519  
-							endsToEat++;
520  
-
521  
-						if (valueChar == JsWriter.MapEndChar)
522  
-							endsToEat--;
523  
-					}
524  
-					return value.Substring(tokenStartPos, i - tokenStartPos);
525  
-
526  
-				//Is List, i.e. [...]
527  
-				case JsWriter.ListStartChar:
528  
-					while (++i < valueLength && endsToEat > 0)
529  
-					{
530  
-						valueChar = value[i];
531  
-
532  
-						if (valueChar == JsonUtils.EscapeChar)
533  
-						{
534  
-							i++;
535  
-							continue;
536  
-						}
537  
-
538  
-						if (valueChar == JsWriter.QuoteChar)
539  
-							withinQuotes = !withinQuotes;
540  
-
541  
-						if (withinQuotes)
542  
-							continue;
543  
-
544  
-						if (valueChar == JsWriter.ListStartChar)
545  
-							endsToEat++;
546  
-
547  
-						if (valueChar == JsWriter.ListEndChar)
548  
-							endsToEat--;
549  
-					}
550  
-					return value.Substring(tokenStartPos, i - tokenStartPos);
551  
-			}
552  
-
553  
-			//Is Value
554  
-			while (++i < valueLength)
555  
-			{
556  
-				valueChar = value[i];
557  
-
558  
-				if (valueChar == JsWriter.ItemSeperator
559  
-					|| valueChar == JsWriter.MapEndChar
560  
-					//If it doesn't have quotes it's either a keyword or number so also has a ws boundary
561  
-					|| (valueChar < WhiteSpaceFlags.Length && WhiteSpaceFlags[valueChar])
562  
-				)
563  
-				{
564  
-					break;
565  
-				}
566  
-			}
567  
-
568  
-			var strValue = value.Substring(tokenStartPos, i - tokenStartPos);
569  
-			return strValue == JsonUtils.Null ? null : strValue;
570  
-		}
571  
-	}
  420
+        }
  421
+
  422
+        private static void EatWhitespace(string json, ref int index)
  423
+        {
  424
+            int c;
  425
+            for (; index < json.Length; index++)
  426
+            {
  427
+                c = json[index];
  428
+                if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c])
  429
+                {
  430
+                    break;
  431
+                }
  432
+            }
  433
+        }
  434
+
  435
+        public string EatTypeValue(string value, ref int i)
  436
+        {
  437
+            return EatValue(value, ref i);
  438
+        }
  439
+
  440
+        public bool EatMapStartChar(string value, ref int i)
  441
+        {
  442
+            for (; i < value.Length; i++) { var c = value[i]; if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c]) break; } //Whitespace inline
  443
+            return value[i++] == JsWriter.MapStartChar;
  444
+        }
  445
+
  446
+        public string EatMapKey(string value, ref int i)
  447
+        {
  448
+            return ParseJsonString(value, ref i);
  449
+        }
  450
+
  451
+        public bool EatMapKeySeperator(string value, ref int i)
  452
+        {
  453
+            for (; i < value.Length; i++) { var c = value[i]; if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c]) break; } //Whitespace inline
  454
+            if (value.Length == i) return false;
  455
+            return value[i++] == JsWriter.MapKeySeperator;
  456
+        }
  457
+
  458
+        public bool EatItemSeperatorOrMapEndChar(string value, ref int i)
  459
+        {
  460
+            for (; i < value.Length; i++) { var c = value[i]; if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c]) break; } //Whitespace inline
  461
+
  462
+            if (i == value.Length) return false;
  463
+
  464
+            var success = value[i] == JsWriter.ItemSeperator
  465
+                || value[i] == JsWriter.MapEndChar;
  466
+
  467
+            i++;
  468
+
  469
+            if (success)
  470
+            {
  471
+                for (; i < value.Length; i++) { var c = value[i]; if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c]) break; } //Whitespace inline
  472
+            }
  473
+
  474
+            return success;
  475
+        }
  476
+
  477
+        public string EatValue(string value, ref int i)
  478
+        {
  479
+            var valueLength = value.Length;
  480
+            if (i == valueLength) return null;
  481
+
  482
+            for (; i < value.Length; i++) { var c = value[i]; if (c >= WhiteSpaceFlags.Length || !WhiteSpaceFlags[c]) break; } //Whitespace inline
  483
+
  484
+            var tokenStartPos = i;
  485
+            var valueChar = value[i];
  486
+            var withinQuotes = false;
  487
+            var endsToEat = 1;
  488
+
  489
+            switch (valueChar)
  490
+            {
  491
+                //If we are at the end, return.
  492
+                case JsWriter.ItemSeperator:
  493
+                case JsWriter.MapEndChar:
  494
+                    return null;
  495
+
  496
+                //Is Within Quotes, i.e. "..."
  497
+                case JsWriter.QuoteChar:
  498
+                    return ParseJsonString(value, ref i);
  499
+
  500
+                //Is Type/Map, i.e. {...}
  501
+                case JsWriter.MapStartChar:
  502
+                    while (++i < valueLength && endsToEat > 0)
  503
+                    {
  504
+                        valueChar = value[i];
  505
+
  506
+                        if (valueChar == JsonUtils.EscapeChar)
  507
+                        {
  508
+                            i++;
  509
+                            continue;
  510
+                        }
  511
+
  512
+                        if (valueChar == JsWriter.QuoteChar)
  513
+                            withinQuotes = !withinQuotes;
  514
+
  515
+                        if (withinQuotes)
  516
+                            continue;
  517
+
  518
+                        if (valueChar == JsWriter.MapStartChar)
  519
+                            endsToEat++;
  520
+
  521
+                        if (valueChar == JsWriter.MapEndChar)
  522
+                            endsToEat--;
  523
+                    }
  524
+                    return value.Substring(tokenStartPos, i - tokenStartPos);
  525
+
  526
+                //Is List, i.e. [...]
  527
+                case JsWriter.ListStartChar:
  528
+                    while (++i < valueLength && endsToEat > 0)
  529
+                    {
  530
+                        valueChar = value[i];
  531
+
  532
+                        if (valueChar == JsonUtils.EscapeChar)
  533
+                        {
  534
+                            i++;
  535
+                            continue;
  536
+                        }
  537
+
  538
+                        if (valueChar == JsWriter.QuoteChar)
  539
+                            withinQuotes = !withinQuotes;
  540
+
  541
+                        if (withinQuotes)
  542
+                            continue;
  543
+
  544
+                        if (valueChar == JsWriter.ListStartChar)
  545
+                            endsToEat++;
  546
+
  547
+                        if (valueChar == JsWriter.ListEndChar)
  548
+                            endsToEat--;
  549
+                    }
  550
+                    return value.Substring(tokenStartPos, i - tokenStartPos);
  551
+            }
  552
+
  553
+            //Is Value
  554
+            while (++i < valueLength)
  555
+            {
  556
+                valueChar = value[i];
  557
+
  558
+                if (valueChar == JsWriter.ItemSeperator
  559
+                    || valueChar == JsWriter.MapEndChar
  560
+                    //If it doesn't have quotes it's either a keyword or number so also has a ws boundary
  561
+                    || (valueChar < WhiteSpaceFlags.Length && WhiteSpaceFla