示例#1
0
        /// <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);
            }
        }
示例#2
0
        /// <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.");
            }
        }
示例#3
0
        /// <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.
        /// </summary>
        /// <param name="path">JSON path to the value we're reading</param>
        /// <param name="pbr">a pushback reader</param>
        /// <returns>the next JSON value</returns>
        /// <exception cref="System.IO.IOException" />
        /// <exception cref="Gavaghan.JSON.JSONException" />
        public IJSONValue Read(string path, PushbackReader pbr)
        {
            IJSONValue value;
            char       c = Demand(pbr);

            // is it a string?
            if (c == '\"')
            {
                value = OnString(path, pbr);
            }
            // is it a number?
            else if (Char.IsDigit(c) || (c == '-'))
            {
                value = OnNumber(path, pbr);
            }
            // is it an array?
            else if (c == '[')
            {
                value = OnArray(path, pbr);
            }
            // is it an object?
            else if (c == '{')
            {
                value = OnObject(path, pbr);
            }
            // is it a boolean?
            else if ((c == 't') || (c == 'f'))
            {
                value = OnBoolean(path, pbr);
            }
            // is it a null?
            else if (c == 'n')
            {
                value = OnNull(path, pbr);
            }
            // else, value type
            else
            {
                value = OnUnknown(path, pbr, c);
            }

            // unread trigger character
            pbr.Unread(c);

            // implementation specific read
            value.Read(path, pbr);

            // give subtype a chance to select a different implementation
            IJSONValue recast = Recast(path, value);

            // if value was recast, copy over original data
            if (recast != null)
            {
                recast.CopyValue(value);
                value = recast;
            }

            return(value);
        }
示例#5
0
        /// <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;
            }
        }
示例#6
0
        /// <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 JSON value that comes after the whitespace (if any).
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        /// <exception cref="System.IO.IOException" />
        /// <exception cref="Gavaghan.JSON.JSONException" />
        public IJSONValue Read(TextReader reader)
        {
            PushbackReader pbr = new PushbackReader(reader, PushbackBufferSize);

            // look for start of value
            SkipWhitespace(pbr);
            int c = pbr.Read();

            // bail out early if EOF
            if (c < 0)
            {
                return(null);
            }

            pbr.Unread(c);

            return(Read("$", pbr));
        }
示例#8
0
        /// <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>
        /// Skip to first non-whitespace character.
        /// </summary>
        /// <param name="pbr">a pushback reader</param>
        /// <exception cref="System.IO.IOException"/>
        public virtual void SkipWhitespace(PushbackReader pbr)
        {
            for (; ;)
            {
                int c = pbr.Read();

                if (c < 0)
                {
                    break;        // bail on EOF
                }
                // if non-whitespace found, push it back and exit
                if (!IsWhitespace(c))
                {
                    pbr.Unread(c);
                    break;
                }
            }
        }
        /// <summary>
        /// Throw away characters until the line comment is completely read.
        /// </summary>
        /// <param name="pbr">the PushbackReader to use</param>
        /// <exception cref="System.IO.IOException"/>
        /// <exception cref="Gavaghan.JSON.JSONException"/>
        private void SkipLineComment(PushbackReader pbr)
        {
            for (; ;)
            {
                int c = pbr.Read();

                // out of data? quit
                if (c < 0)
                {
                    break;
                }

                // end of line? quit
                if ((c == '\n') || (c == '\r'))
                {
                    break;
                }
            }
        }
        /// <summary>
        /// Throw away characters until the block comment is completely read.
        /// </summary>
        /// <param name="pbr">the PushbackReader to use</param>
        /// <exception cref="System.IO.IOException"/>
        /// <exception cref="Gavaghan.JSON.JSONException"/>
        private void SkipBlockComment(PushbackReader pbr)
        {
            bool star = false;

            for (; ;)
            {
                int c = pbr.Read();

                // out of data? throw exception
                if (c < 0)
                {
                    throw new JSONException("$", "Unterminated block comment at end of file");
                }

                if (star && (c == '/'))
                {
                    break;
                }

                star = (c == '*');
            }
        }
        /// <summary>
        /// Skip until the first non-whitespace character where comments are
        /// also treated as whitespace.
        /// </summary>
        /// <param name="pbr"></param>
        /// <exception cref="System.IO.IOException"/>
        /// <exception cref="Gavaghan.JSON.JSONException"/>
        public override void SkipWhitespace(PushbackReader pbr)
        {
            for (; ;)
            {
                int c = pbr.Read();

                if (c < 0)
                {
                    break;        // bail on EOF
                }
                if (!IsWhitespace(c))
                {
                    // it's not whitespace, so see if it's the start of a comment
                    if (c == '/')
                    {
                        int next = pbr.Read();

                        // is it a line comment?
                        if (next == '/')
                        {
                            SkipLineComment(pbr);
                            continue;
                        }
                        // is it a block comment?
                        else if (next == '*')
                        {
                            SkipBlockComment(pbr);
                            continue;
                        }

                        // else, unread - it's the end of the whitespace
                        pbr.Unread(c);
                    }

                    pbr.Unread(c);
                    break;
                }
            }
        }
示例#13
0
        /// <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);
            }
        }
示例#14
0
 /// <summary>
 /// Callback for the start of an unknown type.
 /// </summary>
 /// <param name="path"></param>
 /// <param name="pbr"></param>
 /// <returns></returns>
 /// <exception cref="System.IO.IOException" />
 /// <exception cref="Gavaghan.JSON.JSONException" />
 protected virtual IJSONValue OnUnknown(String path, PushbackReader pbr, char c) => throw new JSONException(path, "Illegal start of JSON value: " + c);
示例#15
0
 /// <summary>
 /// Callback when a null is encountered.
 /// </summary>
 /// <param name="path"></param>
 /// <param name="pbr"></param>
 /// <returns></returns>
 /// <exception cref="System.IO.IOException" />
 /// <exception cref="Gavaghan.JSON.JSONException" />
 protected virtual IJSONValue OnNull(String path, PushbackReader pbr) => JSONNull.INSTANCE;
示例#16
0
 /// <summary>
 /// Callback when a boolean is encountered.
 /// </summary>
 /// <param name="path"></param>
 /// <param name="pbr"></param>
 /// <returns></returns>
 /// <exception cref="System.IO.IOException" />
 /// <exception cref="Gavaghan.JSON.JSONException" />
 protected virtual IJSONValue OnBoolean(String path, PushbackReader pbr) => new JSONBoolean();
示例#17
0
 /// <summary>
 /// Callback when an object is encountered.
 /// </summary>
 /// <param name="path"></param>
 /// <param name="pbr"></param>
 /// <returns></returns>
 /// <exception cref="System.IO.IOException" />
 /// <exception cref="Gavaghan.JSON.JSONException" />
 protected virtual IJSONValue OnObject(String path, PushbackReader pbr) => new JSONObject(this);
示例#18
0
 /// <summary>
 /// Callback when an array is encountered.
 /// </summary>
 /// <param name="path"></param>
 /// <param name="pbr"></param>
 /// <returns></returns>
 /// <exception cref="System.IO.IOException" />
 /// <exception cref="Gavaghan.JSON.JSONException" />
 protected virtual IJSONValue OnArray(String path, PushbackReader pbr) => new JSONArray(this);
示例#19
0
 /// <summary>
 /// Callback when a number is encountered.
 /// </summary>
 /// <param name="path"></param>
 /// <param name="pbr"></param>
 /// <returns></returns>
 /// <exception cref="System.IO.IOException" />
 /// <exception cref="Gavaghan.JSON.JSONException" />
 protected virtual IJSONValue OnNumber(String path, PushbackReader pbr) => new JSONNumber();
示例#20
0
        /// <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;
        }
示例#21
0
 /// <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)
 {
     mValue = ReadString(path, pbr);
 }
示例#22
0
        /// <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());
        }
示例#23
0
 /// <summary>
 /// Callback when a string is encountered.
 /// </summary>
 /// <param name="path"></param>
 /// <param name="pbr"></param>
 /// <returns></returns>
 /// <exception cref="System.IO.IOException" />
 /// <exception cref="Gavaghan.JSON.JSONException" />
 protected virtual IJSONValue OnString(String path, PushbackReader pbr) => new JSONString();
示例#24
0
 /// <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 abstract void Read(string path, PushbackReader pbr);