/// <summary>
 /// Internal init constuctor.
 /// </summary>
 internal JSonReaderException(string message, JSonReaderTokenInfo token)
     : base(PrepareMessage(message, token))
 {
     InvalidToken = token != null ? token.Text : string.Empty;
     Line = token != null ? token.Line : 0;
     Offset = token != null ? token.Offset : 0;
 }
Example #2
0
        /// <summary>
        /// Reads a keyword from the input stream.
        /// </summary>
        private object ReadKeyword()
        {
            JSonReaderTokenInfo topToken = PopTopToken();

            // top token contains the first letter of current keyword:
            StringBuilder buffer     = new StringBuilder(topToken.Text);
            int           lastLine   = _input.Line;
            int           lastOffset = _input.LineOffset;

            StringHelper.ReadKeywordChars(_input, buffer);

            // since keyword has no closing token (as arrays or strings), it might
            // happen that we read too many chars... so put that new char as a token on the
            // stack and instruct reader that token is already there...
            ReadNextToken(char.IsWhiteSpace(_input.CurrentChar));
            _getTokenFromStack = true;

            string keyword = buffer.ToString().ToLower();

            foreach (var k in AvailableKeywords)
            {
                if (k.Token == keyword)
                {
                    return(_factory.CreateKeyword(k));
                }
            }

            // token has not been found:
            throw new JSonReaderException("Unknown keyword", keyword, lastLine, lastOffset);
        }
 /// <summary>
 /// Internal init constuctor.
 /// </summary>
 internal JSonReaderException(string message, JSonReaderTokenInfo token)
     : base(PrepareMessage(message, token))
 {
     InvalidToken = token != null ? token.Text : string.Empty;
     Line         = token != null ? token.Line : 0;
     Offset       = token != null ? token.Offset : 0;
 }
        private static string PrepareMessage(string message, JSonReaderTokenInfo token)
        {
            if (token != null)
            {
                return(PrepareMessage(message, token.Text, token.Line, token.Offset));
            }

            return(PrepareMessage(message, string.Empty, 0, 0));
        }
Example #5
0
        /// <summary>
        /// Read number from an input stream.
        /// </summary>
        private object ReadNumber()
        {
            JSonReaderTokenInfo topToken = PopTopToken();

            // top token contains the first letter of current number:
            StringBuilder buffer       = new StringBuilder(topToken.Text);
            int           numberOffset = _input.LineOffset;

            StringHelper.ReadDecimalNumberChars(_input, buffer);

            // verify what kind of character is just after the number, if it's a letter then it is an error,
            // the only allowed are white-chars and JSON object separators (comma, ']', '}')!
            if (!_input.IsEof)
            {
                if (_input.CurrentChar != ',' && !char.IsWhiteSpace(_input.CurrentChar) && _input.CurrentChar != ']' && _input.CurrentChar != '}')
                {
                    buffer.Append(_input.CurrentChar);
                    throw new JSonReaderException("Invalid number", buffer.ToString(), _input.Line, numberOffset);
                }
            }

            // since number has no closing token (as arrays or strings), it might
            // happen that we read too many chars... so put that new char as a token on the
            // stack and instruct reader that token is already there...
            ReadNextToken(char.IsWhiteSpace(_input.CurrentChar));
            _getTokenFromStack = true;

            string number = buffer.ToString();
            object result = _factory.CreateNumber(number);

            if (result != null)
            {
                return(result);
            }

            // number had some invalid format:
            throw new JSonReaderException(string.Concat("Invalid number format, value: \"", number, "\", expected format: ", _factory.Format),
                                          number, _input.Line, numberOffset);
        }
        private static string PrepareMessage(string message, JSonReaderTokenInfo token)
        {
            if (token != null)
                return PrepareMessage(message, token.Text, token.Line, token.Offset);

            return PrepareMessage(message, string.Empty, 0, 0);
        }
Example #7
0
        /// <summary>
        /// Adds value to the dictionary.
        /// </summary>
        private static void AddValue(IDictionary<string, object> result, ref string name, object value, ref bool colonSpot, ref bool commaSpot, JSonReaderTokenInfo currentToken)
        {
            if (!colonSpot)
                throw new JSonReaderException("Missing colon between name and value definition", currentToken);

            if (!commaSpot && result.Count > 0)
                throw new JSonReaderException("Missing comma before name and value definition", currentToken);

            if (name == null)
                throw new JSonReaderException("Missing value for object element", currentToken);

            if (result.ContainsKey(name))
                throw new JSonReaderException("Duplicated name in object", currentToken);

            result.Add(name, value);
            name = null;
            colonSpot = false;
            commaSpot = false;
        }
Example #8
0
        /// <summary>
        /// Adds new element to an array.
        /// </summary>
        private static void AddValue(ICollection<object> result, object value, int commas, JSonReaderTokenInfo currentToken)
        {
            if (result.Count != commas)
                throw new JSonReaderException("Missing commas between array objects", currentToken);

            result.Add(value);
        }
Example #9
0
        /// <summary>
        /// Reads next token from the input source with a possibility to treat already known character as the one read.
        /// Option required mostly for JSON elements that don't have a closing tokens (i.e.: ']' for arrays) and used for number and keywords.
        /// </summary>
        private JSonReaderTokenInfo ReadNextToken(bool fromCurrentChar)
        {
            // token was already read in advanced and put on the stack:
            if (_getTokenFromStack)
            {
                _getTokenFromStack = false;

                // reached end of input stream:
                if (_input.IsEof)
                    return new JSonReaderTokenInfo(string.Empty, JSonReaderTokenType.EndOfText, _input.Line, _input.LineOffset);

                if (_tokens.Count == 0)
                    throw new JSonReaderException("Lack of tokens", (JSonReaderTokenInfo)null);

                return _tokens.Peek();
            }

            if (fromCurrentChar)
            {
                // clear the whitespace characters:
                StringHelper.ReadWhiteChars(_input);
            }

            // reached end of input stream:
            if (_input.IsEof)
                return new JSonReaderTokenInfo(string.Empty, JSonReaderTokenType.EndOfText, _input.Line, _input.LineOffset);

            char tokenChar = _input.CurrentChar;
            string tokenString = tokenChar.ToString();
            JSonReaderTokenType tokenType = JSonReaderTokenType.Unknown;

            // check if this is one of the already known tokens...
            foreach (var tokenDef in AvailableTokens)
                if (tokenDef.Token == tokenChar)
                {
                    tokenType = tokenDef.Type;
                    break;
                }

            // is this the beginning of a keyword?
            if (tokenType == JSonReaderTokenType.Unknown && char.IsLetter(tokenChar))
                tokenType = JSonReaderTokenType.Keyword;

            // is this the beginning of the number?
            if (tokenType == JSonReaderTokenType.Unknown && (char.IsDigit(tokenChar) || tokenChar == '-'))
                tokenType = JSonReaderTokenType.Number;

            // if this is still unknown element...
            if (tokenType == JSonReaderTokenType.Unknown)
                throw new JSonReaderException("Invalid token found", tokenString, _input.Line, _input.LineOffset);

            JSonReaderTokenInfo nextToken = new JSonReaderTokenInfo(tokenString, tokenType, _input.Line, _input.LineOffset);

            _tokens.Push(nextToken);

            // return it:
            return nextToken;
        }
Example #10
0
        /// <summary>
        /// Reads a dictonary from an input stream.
        /// </summary>
        private object ReadObject()
        {
            Dictionary <string, object> result = new Dictionary <string, object>();
            JSonReaderTokenInfo         currentToken;
            string name      = null;
            bool   colonSpot = false;
            bool   commaSpot = false;
            int    commas    = 0;

            while ((currentToken = ReadNextToken(true)).Type != JSonReaderTokenType.EndOfText)
            {
                if (currentToken.Type == JSonReaderTokenType.ObjectEnd)
                {
                    PopTopToken();

                    // if number of commas is greater than number of added elements,
                    // then value was not passed between:
                    if (commas > 0 && commas >= result.Count)
                    {
                        throw new JSonReaderException("Too many commas at closing object token, expected none", currentToken);
                    }
                    break;
                }

                switch (currentToken.Type)
                {
                case JSonReaderTokenType.ArrayStart:

                    // read embedded array:
                    AddValue(result, ref name, ReadArray(), ref colonSpot, ref commaSpot, currentToken);
                    break;

                case JSonReaderTokenType.ObjectStart:

                    // read embedded object:
                    AddValue(result, ref name, ReadObject(), ref colonSpot, ref commaSpot, currentToken);
                    break;

                case JSonReaderTokenType.Keyword:

                    if (name == null)
                    {
                        throw new JSonReaderException("Keyword can not be an object element's name", currentToken);
                    }

                    // add embedded value of reserved keyword:
                    AddValue(result, ref name, ReadKeyword(), ref colonSpot, ref commaSpot, currentToken);
                    break;

                case JSonReaderTokenType.Number:

                    // add embedded numeric value:
                    AddValue(result, ref name, ReadNumber(), ref colonSpot, ref commaSpot, currentToken);
                    break;

                case JSonReaderTokenType.String:

                    if (!commaSpot && result.Count > 0)
                    {
                        throw new JSonReaderException("Missing comma before name and value definition", currentToken);
                    }

                    if (name == null)
                    {
                        name = ReadString().ToString();

                        if (result.ContainsKey(name))
                        {
                            throw new JSonReaderException("Duplicated name in object", currentToken);
                        }

                        break;
                    }

                    // add embedded string:
                    AddValue(result, ref name, ReadString(), ref colonSpot, ref commaSpot, currentToken);
                    break;

                case JSonReaderTokenType.Colon:
                    PopTopToken();

                    if (colonSpot)
                    {
                        throw new JSonReaderException("Duplicated colon found in object", currentToken);
                    }

                    if (name == null)
                    {
                        throw new JSonReaderException("Unexpected colon, when name not given", currentToken);
                    }

                    colonSpot = true;
                    break;

                case JSonReaderTokenType.Comma:

                    // go to next array element:
                    currentToken = PopTopToken();

                    if (commaSpot)
                    {
                        throw new JSonReaderException("Two commans in a row", currentToken);
                    }

                    commas++;
                    commaSpot = true;

                    // if number of commas is greater than number of added elements,
                    // then value was not passed between:
                    if (commas > result.Count)
                    {
                        throw new JSonReaderException("Missing value for object element", currentToken);
                    }
                    break;

                default:
                    throw new JSonReaderException("Invalid token", currentToken);
                }
            }

            JSonReaderTokenInfo topToken = PopTopToken();

            if (topToken.Type != JSonReaderTokenType.ObjectStart || currentToken.Type == JSonReaderTokenType.EndOfText)
            {
                throw new JSonReaderException("Missing close object token", topToken);
            }

            return(_factory.CreateObject(result));
        }
Example #11
0
        /// <summary>
        /// Adds value to the dictionary.
        /// </summary>
        private static void AddValue(IDictionary <string, object> result, ref string name, object value, ref bool colonSpot, ref bool commaSpot, JSonReaderTokenInfo currentToken)
        {
            if (!colonSpot)
            {
                throw new JSonReaderException("Missing colon between name and value definition", currentToken);
            }

            if (!commaSpot && result.Count > 0)
            {
                throw new JSonReaderException("Missing comma before name and value definition", currentToken);
            }

            if (name == null)
            {
                throw new JSonReaderException("Missing value for object element", currentToken);
            }

            if (result.ContainsKey(name))
            {
                throw new JSonReaderException("Duplicated name in object", currentToken);
            }

            result.Add(name, value);
            name      = null;
            colonSpot = false;
            commaSpot = false;
        }
Example #12
0
        /// <summary>
        /// Read an array from input stream.
        /// </summary>
        private object ReadArray()
        {
            List <object>       result = new List <object>();
            JSonReaderTokenInfo currentToken;
            int commas = 0;

            while ((currentToken = ReadNextToken(true)).Type != JSonReaderTokenType.EndOfText)
            {
                if (currentToken.Type == JSonReaderTokenType.ArrayEnd)
                {
                    PopTopToken();

                    // if number of commas is greater than number of added elements,
                    // then value was not passed between:
                    if (result.Count > 0 && commas != result.Count - 1)
                    {
                        throw new JSonReaderException("Too many commas at closing array token, expected none", currentToken);
                    }
                    break;
                }

                switch (currentToken.Type)
                {
                case JSonReaderTokenType.ArrayStart:
                    // read embedded array:
                    AddValue(result, ReadArray(), commas, currentToken);
                    break;

                case JSonReaderTokenType.ObjectStart:
                    // read embedded object:
                    AddValue(result, ReadObject(), commas, currentToken);
                    break;

                case JSonReaderTokenType.Keyword:
                    // add embedded value of reserved keyword:
                    AddValue(result, ReadKeyword(), commas, currentToken);
                    break;

                case JSonReaderTokenType.Number:
                    // add embedded numeric value:
                    AddValue(result, ReadNumber(), commas, currentToken);
                    break;

                case JSonReaderTokenType.String:
                    // add embedded string value:
                    AddValue(result, ReadString(), commas, currentToken);
                    break;

                case JSonReaderTokenType.Comma:
                    // go to next array element:
                    currentToken = PopTopToken();
                    commas++;

                    // if number of commas is greater than number of added elements,
                    // then value was not passed between:
                    if (commas > result.Count)
                    {
                        throw new JSonReaderException("Missing value for array element", currentToken);
                    }
                    break;

                default:
                    throw new JSonReaderException("Invalid token", currentToken);
                }
            }

            JSonReaderTokenInfo topToken = PopTopToken();

            if (topToken.Type != JSonReaderTokenType.ArrayStart || currentToken.Type == JSonReaderTokenType.EndOfText)
            {
                throw new JSonReaderException("Missing close array token", topToken);
            }

            return(_factory.CreateArray(result));
        }
Example #13
0
        /// <summary>
        /// Adds new element to an array.
        /// </summary>
        private static void AddValue(ICollection <object> result, object value, int commas, JSonReaderTokenInfo currentToken)
        {
            if (result.Count != commas)
            {
                throw new JSonReaderException("Missing commas between array objects", currentToken);
            }

            result.Add(value);
        }
Example #14
0
        /// <summary>
        /// Reads next token from the input source with a possibility to treat already known character as the one read.
        /// Option required mostly for JSON elements that don't have a closing tokens (i.e.: ']' for arrays) and used for number and keywords.
        /// </summary>
        private JSonReaderTokenInfo ReadNextToken(bool fromCurrentChar)
        {
            // token was already read in advanced and put on the stack:
            if (_getTokenFromStack)
            {
                _getTokenFromStack = false;

                // reached end of input stream:
                if (_input.IsEof)
                {
                    return(new JSonReaderTokenInfo(string.Empty, JSonReaderTokenType.EndOfText, _input.Line, _input.LineOffset));
                }

                if (_tokens.Count == 0)
                {
                    throw new JSonReaderException("Lack of tokens", (JSonReaderTokenInfo)null);
                }

                return(_tokens.Peek());
            }

            if (fromCurrentChar)
            {
                // clear the whitespace characters:
                StringHelper.ReadWhiteChars(_input);
            }

            // reached end of input stream:
            if (_input.IsEof)
            {
                return(new JSonReaderTokenInfo(string.Empty, JSonReaderTokenType.EndOfText, _input.Line, _input.LineOffset));
            }

            char   tokenChar              = _input.CurrentChar;
            string tokenString            = tokenChar.ToString();
            JSonReaderTokenType tokenType = JSonReaderTokenType.Unknown;

            // check if this is one of the already known tokens...
            foreach (var tokenDef in AvailableTokens)
            {
                if (tokenDef.Token == tokenChar)
                {
                    tokenType = tokenDef.Type;
                    break;
                }
            }

            // is this the beginning of a keyword?
            if (tokenType == JSonReaderTokenType.Unknown && char.IsLetter(tokenChar))
            {
                tokenType = JSonReaderTokenType.Keyword;
            }

            // is this the beginning of the number?
            if (tokenType == JSonReaderTokenType.Unknown && (char.IsDigit(tokenChar) || tokenChar == '-'))
            {
                tokenType = JSonReaderTokenType.Number;
            }

            // if this is still unknown element...
            if (tokenType == JSonReaderTokenType.Unknown)
            {
                throw new JSonReaderException("Invalid token found", tokenString, _input.Line, _input.LineOffset);
            }

            JSonReaderTokenInfo nextToken = new JSonReaderTokenInfo(tokenString, tokenType, _input.Line, _input.LineOffset);

            _tokens.Push(nextToken);

            // return it:
            return(nextToken);
        }