/// <summary> /// Read the fractional part of the number. /// </summary> /// <param name="path">path to the value being read</param> /// <param name="pbr"></param> /// <param name="builder"></param> /// <exception cref="System.IO.IOException"/> /// <exception cref="Gavaghan.JSON.JSONException"/> private void ReadFractionalPart(string path, PushbackReader pbr, StringBuilder builder) { char c; c = JSONValueFactory.Demand(pbr); if (c == '.') { builder.Append(c); for (; ;) { c = JSONValueFactory.Demand(pbr); if (!Char.IsDigit(c)) { if (builder.ToString().EndsWith(".")) { throw new JSONException(path, "Digits expected after decimal points."); } pbr.Unread(c); break; } builder.Append(c); } } else { pbr.Unread(c); } }
/// <summary> /// Read a JSON value (presumes the key has already been read) and set the /// underlying value. There's generally no reason to call this method /// directly. It is intended to be overridden by an extended type. /// </summary> /// <param name="path">path to the value being read</param> /// <param name="pbr">source reader</param> /// <exception cref="Gavaghan.JSON.JSONException">on grammar error</exception> /// <exception cref="System.IO.IOException">on read failure</exception> public override void Read(string path, PushbackReader pbr) { StringBuilder builder = new StringBuilder(); char c = JSONValueFactory.Demand(pbr); if (!Char.IsDigit(c) && (c != '-')) { throw new JSONException(path, "Content does not appear to be a number."); } builder.Append(c); // read the number if (c != '0') { ReadWholePart(pbr, builder); } ReadFractionalPart(path, pbr, builder); ReadExponent(path, pbr, builder); // parse and set value try { mValue = Decimal.Parse(builder.ToString(), NumberStyles.AllowExponent | NumberStyles.Float); } catch (FormatException) { throw new JSONException(path, "Illegal number format: " + builder.ToString()); } }
/// <summary> /// Read a JSON value (presumes the key has already been read) and set the /// underlying value. There's generally no reason to call this method /// directly. It is intended to be overridden by an extended type. /// </summary> /// <param name="path">path to the value being read</param> /// <param name="pbr">source reader</param> /// <exception cref="Gavaghan.JSON.JSONException">on grammar error</exception> /// <exception cref="System.IO.IOException">on read failure</exception> public override void Read(string path, PushbackReader pbr) { char c = JSONValueFactory.Demand(pbr); if (c == 'n') { if (JSONValueFactory.Demand(pbr) != 'u') { throw new JSONException(path, "Content does not appear to be a null."); } if (JSONValueFactory.Demand(pbr) != 'l') { throw new JSONException(path, "Content does not appear to be a null."); } if (JSONValueFactory.Demand(pbr) != 'l') { throw new JSONException(path, "Content does not appear to be a null."); } } else { throw new JSONException(path, "Content does not appear to be a null."); } }
/// <summary> /// Read a JSON value (presumes the key has already been read) and set the /// underlying value. There's generally no reason to call this method /// directly. It is intended to be overridden by an extended type. /// </summary> /// <param name="path">path to the value being read</param> /// <param name="pbr">source reader</param> /// <exception cref="Gavaghan.JSON.JSONException">on grammar error</exception> /// <exception cref="System.IO.IOException">on read failure</exception> public override void Read(string path, PushbackReader pbr) { char c = JSONValueFactory.Demand(pbr); if (c != '[') { throw new JSONException(path, "Content does not appear to be an array."); } // empty array is an easy out mFactory.SkipWhitespace(pbr); c = JSONValueFactory.Demand(pbr); if (c == ']') { return; } pbr.Unread(c); // loop through values try { for (; ;) { IJSONValue value = mFactory.Read(path, pbr); mValue.Add(value); // get next non-whitespace mFactory.SkipWhitespace(pbr); c = JSONValueFactory.Demand(pbr); // is end? if (c == ']') { return; } // is more if (c == ',') { mFactory.SkipWhitespace(pbr); continue; } throw new JSONException(path, "Incorrectly formatted array: " + c); } } finally { mFactory = null; } }
/// <summary> /// Read a JSON value (presumes the key has already been read) and set the /// underlying value. There's generally no reason to call this method /// directly. It is intended to be overridden by an extended type. /// </summary> /// <param name="path">path to the value being read</param> /// <param name="pbr">source reader</param> /// <exception cref="Gavaghan.JSON.JSONException">on grammar error</exception> /// <exception cref="System.IO.IOException">on read failure</exception> public override void Read(string path, PushbackReader pbr) { char c = JSONValueFactory.Demand(pbr); if (c == 't') { if (JSONValueFactory.Demand(pbr) != 'r') { throw new JSONException(path, "Content does not appear to be a boolean."); } if (JSONValueFactory.Demand(pbr) != 'u') { throw new JSONException(path, "Content does not appear to be a boolean."); } if (JSONValueFactory.Demand(pbr) != 'e') { throw new JSONException(path, "Content does not appear to be a boolean."); } mValue = true; } else if (c == 'f') { if (JSONValueFactory.Demand(pbr) != 'a') { throw new JSONException(path, "Content does not appear to be a boolean."); } if (JSONValueFactory.Demand(pbr) != 'l') { throw new JSONException(path, "Content does not appear to be a boolean."); } if (JSONValueFactory.Demand(pbr) != 's') { throw new JSONException(path, "Content does not appear to be a boolean."); } if (JSONValueFactory.Demand(pbr) != 'e') { throw new JSONException(path, "Content does not appear to be a boolean."); } mValue = false; } else { throw new JSONException(path, "Content does not appear to be a boolean."); } }
/// <summary> /// Read the whole portion of a number. /// </summary> /// <param name="pbr"></param> /// <param name="builder"></param> /// <exception cref="System.IO.IOException"/> /// <exception cref="Gavaghan.JSON.JSONException"/> private void ReadWholePart(PushbackReader pbr, StringBuilder builder) { char c; for (; ;) { c = JSONValueFactory.Demand(pbr); if (Char.IsDigit(c)) { builder.Append(c); } else { pbr.Unread(c); break; } } }
/// <summary> /// Read the exponent. /// </summary> /// <param name="path">path to the value being read</param> /// <param name="pbr"></param> /// <param name="builder"></param> /// <exception cref="System.IO.IOException"/> /// <exception cref="Gavaghan.JSON.JSONException"/> private void ReadExponent(string path, PushbackReader pbr, StringBuilder builder) { char c; c = JSONValueFactory.Demand(pbr); if (c == 'e' || (c == 'E')) { builder.Append(c); c = JSONValueFactory.Demand(pbr); if (Char.IsDigit(c) || (c == '+') || (c == '-')) { builder.Append(c); for (; ;) { c = JSONValueFactory.Demand(pbr); if (!Char.IsDigit(c)) { pbr.Unread(c); break; } builder.Append(c); } } else { throw new JSONException(path, "Content does not appear to be a number"); } } else { pbr.Unread(c); } }
/// <summary> /// Read a string value. /// </summary> /// <param name="path">path to the value being read</param> /// <param name="pbr"></param> /// <returns></returns> /// <exception cref="System.IO.IOOException"/> /// <exception cref="Gavaghan.JSON.JSNException"/> static public string ReadString(string path, PushbackReader pbr) { StringBuilder builder = new StringBuilder(); char c = JSONValueFactory.Demand(pbr); if (c != '\"') { throw new JSONException(path, "Leading quote expected at start of string."); } for (; ;) { c = JSONValueFactory.Demand(pbr); // if closing quote if (c == '\"') { break; } // if escape if (c == '\\') { c = JSONValueFactory.Demand(pbr); switch (c) { case '\"': case '/': case '\\': builder.Append(c); break; case 'b': builder.Append('\b'); break; case 'f': builder.Append('\f'); break; case 'n': builder.Append('\n'); break; case 'r': builder.Append('\r'); break; case 't': builder.Append('\t'); break; case 'u': StringBuilder hex = new StringBuilder(); hex.Append(JSONValueFactory.Demand(pbr)); hex.Append(JSONValueFactory.Demand(pbr)); hex.Append(JSONValueFactory.Demand(pbr)); hex.Append(JSONValueFactory.Demand(pbr)); try { int uchar = Int32.Parse(hex.ToString(), NumberStyles.HexNumber); builder.Append((char)uchar); } catch (FormatException) { throw new JSONException(path, "Illegal unicode value: " + hex.ToString()); } break; default: throw new JSONException(path, "Illegal escape value in string: " + c); } } else { builder.Append(c); } } return(builder.ToString()); }
/// <summary> /// Create a new JSONObject /// </summary> /// <param name="factory">the factory implementation used to read values in the object</param> public JSONObject(JSONValueFactory factory) { mFactory = factory; }
/// <summary> /// Read a JSON value (presumes the key has already been read) and set the /// underlying value. There's generally no reason to call this method /// directly. It is intended to be overridden by an extended type. /// </summary> /// <param name="path">path to the value being read</param> /// <param name="pbr">source reader</param> /// <exception cref="Gavaghan.JSON.JSONException">on grammar error</exception> /// <exception cref="System.IO.IOException">on read failure</exception> public virtual void Read(string path, PushbackReader pbr) { // assert we have an opening brace char c = JSONValueFactory.Demand(pbr); if (c != '{') { throw new JSONException(path, "Failed to find '{' at start of JSON object."); } for (; ;) { string key; // next is either a key or a closing brace mFactory.SkipWhitespace(pbr); c = JSONValueFactory.Demand(pbr); // is it a string? if (c == '\"') { pbr.Unread(c); key = JSONString.ReadString(path, pbr); } // is it a closing brace? else if (c == '}') { break; } // else, it's poorly formed else { throw new JSONException(path, "JSON object is not grammatically correct. Unexpected: " + c); } // next ought to be a colon mFactory.SkipWhitespace(pbr); c = JSONValueFactory.Demand(pbr); if (c != ':') { throw new JSONException(path + "." + key, "Expected ':' after key value"); } mFactory.SkipWhitespace(pbr); // next, read a JSONValue IJSONValue value = mFactory.Read(path + "." + key, pbr); // add it to the map Add(key, value); // next must be comma or close mFactory.SkipWhitespace(pbr); c = JSONValueFactory.Demand(pbr); if (c == ',') { continue; } if (c == '}') { break; } throw new JSONException(path, "JSON object is not grammatically correct. Unexpected: " + c); } mFactory = null; }
/// <summary> /// Create a new JSONArray. /// </summary> /// <param name="factory">the <code>JSONValueFactory</code> implementation used to read JSON values.</param> public JSONArray(JSONValueFactory factory) { mValue = new List <IJSONValue>(); mFactory = factory; }