Exemplo n.º 1
0
        private CBORObject NextJSONNegativeNumber(
            int[] nextChar,
            int depth)
        {
            string     str;
            CBORObject obj;
            int        c = this.ReadChar();

            if (c < '0' || c > '9')
            {
                this.RaiseError("JSON number can't be parsed.");
            }
            int cval   = -(c - '0');
            int cstart = c;

            c       = this.ReadChar();
            this.sb = this.sb ?? new StringBuilder();
            this.sb.Remove(0, this.sb.Length);
            this.sb.Append('-');
            this.sb.Append((char)cstart);
            var charbuf    = new char[32];
            var charbufptr = 0;

            while (c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                   c == 'e' || c == 'E')
            {
                charbuf[charbufptr++] = (char)c;
                if (charbufptr >= 32)
                {
                    this.sb.Append(charbuf, 0, 32);
                    charbufptr = 0;
                }
                c = this.ReadChar();
            }
            if (charbufptr > 0)
            {
                this.sb.Append(charbuf, 0, charbufptr);
            }
            // DebugUtility.Log("--nega=" + sw.ElapsedMilliseconds + " ms");
            // check if character can validly appear after a JSON number
            if (c != ',' && c != ']' && c != '}' && c != -1 &&
                c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
            {
                this.RaiseError("Invalid character after JSON number");
            }
            str = this.sb.ToString();
            // DebugUtility.Log("negb=" + sw.ElapsedMilliseconds + " ms");
            obj = CBORDataUtilities.ParseJSONNumber(str, this.options);
            // DebugUtility.Log("str=" + str + " obj=" + (obj));
            // DebugUtility.Log("negc=" + sw.ElapsedMilliseconds + " ms");
            if (obj == null)
            {
                string errstr = (str.Length <= 100) ? str : (str.Substring(0,
                                                                           100) + "...");
                this.RaiseError("JSON number can't be parsed. " + errstr);
            }
            if (c == 0x20 || c == 0x0a || c == 0x0d || c == 0x09)
            {
                nextChar[0] = this.SkipWhitespaceJSON();
            }
            else if (this.jsonSequenceMode && depth == 0)
            {
                nextChar[0] = c;
                this.RaiseError("JSON whitespace expected after top-level " +
                                "number in JSON sequence");
            }
            else
            {
                nextChar[0] = c;
            }
            return(obj);
        }
Exemplo n.º 2
0
        private CBORObject NextJSONValue(
            int firstChar,
            int[] nextChar,
            int depth)
        {
            string     str;
            int        c   = firstChar;
            CBORObject obj = null;

            if (c < 0)
            {
                this.RaiseError("Unexpected end of data");
            }
            switch (c)
            {
            case '"': {
                // Parse a string
                // The tokenizer already checked the string for invalid
                // surrogate pairs, so just call the CBORObject
                // constructor directly
                obj         = CBORObject.FromRaw(this.NextJSONString());
                nextChar[0] = this.SkipWhitespaceJSON();
                return(obj);
            }

            case '{': {
                // Parse an object
                obj         = this.ParseJSONObject(depth + 1);
                nextChar[0] = this.SkipWhitespaceJSON();
                return(obj);
            }

            case '[': {
                // Parse an array
                obj         = this.ParseJSONArray(depth + 1);
                nextChar[0] = this.SkipWhitespaceJSON();
                return(obj);
            }

            case 't': {
                // Parse true
                if ((c = this.ReadChar()) != 'r' || (c = this.ReadChar()) != 'u' ||
                    (c = this.ReadChar()) != 'e')
                {
                    this.RaiseError("Value can't be parsed.");
                }
                c = this.ReadChar();
                if (c == 0x20 || c == 0x0a || c == 0x0d || c == 0x09)
                {
                    nextChar[0] = this.SkipWhitespaceJSON();
                }
                else if (this.jsonSequenceMode && depth == 0)
                {
                    nextChar[0] = c;
                    this.RaiseError("JSON whitespace expected after top-level " +
                                    "number in JSON sequence");
                }
                else
                {
                    nextChar[0] = c;
                }
                return(CBORObject.True);
            }

            case 'f': {
                // Parse false
                if ((c = this.ReadChar()) != 'a' || (c = this.ReadChar()) != 'l' ||
                    (c = this.ReadChar()) != 's' || (c = this.ReadChar()) != 'e')
                {
                    this.RaiseError("Value can't be parsed.");
                }
                c = this.ReadChar();
                if (c == 0x20 || c == 0x0a || c == 0x0d || c == 0x09)
                {
                    nextChar[0] = this.SkipWhitespaceJSON();
                }
                else if (this.jsonSequenceMode && depth == 0)
                {
                    nextChar[0] = c;
                    this.RaiseError("JSON whitespace expected after top-level " +
                                    "number in JSON sequence");
                }
                else
                {
                    nextChar[0] = c;
                }
                return(CBORObject.False);
            }

            case 'n': {
                // Parse null
                if ((c = this.ReadChar()) != 'u' || (c = this.ReadChar()) != 'l' ||
                    (c = this.ReadChar()) != 'l')
                {
                    this.RaiseError("Value can't be parsed.");
                }
                c = this.ReadChar();
                if (c == 0x20 || c == 0x0a || c == 0x0d || c == 0x09)
                {
                    nextChar[0] = this.SkipWhitespaceJSON();
                }
                else if (this.jsonSequenceMode && depth == 0)
                {
                    nextChar[0] = c;
                    this.RaiseError("JSON whitespace expected after top-level " +
                                    "number in JSON sequence");
                }
                else
                {
                    nextChar[0] = c;
                }
                return(CBORObject.Null);
            }

            case '-': {
                // Parse a negative number
                return(this.NextJSONNegativeNumber(nextChar, depth));
            }

            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9': {
                // Parse a nonnegative number
                int cval    = c - '0';
                int cstart  = c;
                var needObj = true;
                c = this.ReadChar();
                if (!(c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                      c == 'e' || c == 'E'))
                {
                    // Optimize for common case where JSON number
                    // is a single digit without sign or exponent
                    obj     = CBORDataUtilities.ParseSmallNumber(cval, this.options);
                    needObj = false;
                }
                else if (c >= '0' && c <= '9')
                {
                    int csecond = c;
                    if (cstart == '0')
                    {
                        // Leading zero followed by any digit is not allowed
                        this.RaiseError("JSON number can't be parsed.");
                    }
                    cval = (cval * 10) + (int)(c - '0');
                    c    = this.ReadChar();
                    if (c >= '0' && c <= '9')
                    {
                        var digits = 2;
                        var ctmp   = new int[10];
                        ctmp[0] = cstart;
                        ctmp[1] = csecond;
                        while (digits < 9 && (c >= '0' && c <= '9'))
                        {
                            cval           = (cval * 10) + (int)(c - '0');
                            ctmp[digits++] = c;
                            c = this.ReadChar();
                        }
                        if (c == 'e' || c == 'E' || c == '.' || (c >= '0' && c <= '9'))
                        {
                            // Not an all-digit number, or too long
                            this.sb = this.sb ?? new StringBuilder();
                            this.sb.Remove(0, this.sb.Length);
                            for (var vi = 0; vi < digits; ++vi)
                            {
                                this.sb.Append((char)ctmp[vi]);
                            }
                        }
                        else
                        {
                            obj     = CBORDataUtilities.ParseSmallNumber(cval, this.options);
                            needObj = false;
                        }
                    }
                    else if (!(c == '-' || c == '+' || c == '.' || c == 'e' || c
                               == 'E'))
                    {
                        // Optimize for common case where JSON number
                        // is two digits without sign, decimal point, or exponent
                        obj     = CBORDataUtilities.ParseSmallNumber(cval, this.options);
                        needObj = false;
                    }
                    else
                    {
                        this.sb = this.sb ?? new StringBuilder();
                        this.sb.Remove(0, this.sb.Length);
                        this.sb.Append((char)cstart);
                        this.sb.Append((char)csecond);
                    }
                }
                else
                {
                    this.sb = this.sb ?? new StringBuilder();
                    this.sb.Remove(0, this.sb.Length);
                    this.sb.Append((char)cstart);
                }
                if (needObj)
                {
                    var charbuf    = new char[32];
                    var charbufptr = 0;
                    while (
                        c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                        c == 'e' || c == 'E')
                    {
                        charbuf[charbufptr++] = (char)c;
                        if (charbufptr >= 32)
                        {
                            this.sb.Append(charbuf, 0, 32);
                            charbufptr = 0;
                        }
                        c = this.ReadChar();
                    }
                    if (charbufptr > 0)
                    {
                        this.sb.Append(charbuf, 0, charbufptr);
                    }
                    // check if character can validly appear after a JSON number
                    if (c != ',' && c != ']' && c != '}' && c != -1 &&
                        c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                    {
                        this.RaiseError("Invalid character after JSON number");
                    }
                    str = this.sb.ToString();
                    obj = CBORDataUtilities.ParseJSONNumber(str, this.options);
                    if (obj == null)
                    {
                        string errstr = (str.Length <= 100) ? str : (str.Substring(0,
                                                                                   100) + "...");
                        this.RaiseError("JSON number can't be parsed. " + errstr);
                    }
                }
                if (c == 0x20 || c == 0x0a || c == 0x0d || c == 0x09)
                {
                    nextChar[0] = this.SkipWhitespaceJSON();
                }
                else if (this.jsonSequenceMode && depth == 0)
                {
                    nextChar[0] = c;
                    this.RaiseError("JSON whitespace expected after top-level " +
                                    "number in JSON sequence");
                }
                else
                {
                    nextChar[0] = c;
                }
                return(obj);
            }

            default: this.RaiseError("Value can't be parsed.");
                break;
            }
            return(null);
        }
Exemplo n.º 3
0
        private CBORObject NextJSONNonnegativeNumber(int c, int[] nextChar)
        {
            // Assumes the last character read was a digit
            CBORObject obj              = null;
            int        cval             = c - '0';
            int        cstart           = c;
            int        startIndex       = this.index - 1;
            var        needObj          = true;
            int        numberStartIndex = this.index - 1;

            c = this.index < this.endPos ? ((int)this.bytes[this.index++]) &
                0xff : -1;
            if (!(c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                  c == 'e' || c == 'E'))
            {
                // Optimize for common case where JSON number
                // is a single digit without sign or exponent
                obj     = CBORDataUtilities.ParseSmallNumber(cval, this.options);
                needObj = false;
            }
            else if (c >= '0' && c <= '9')
            {
                int csecond = c;
                if (cstart == '0')
                {
                    // Leading zero followed by any digit is not allowed
                    this.RaiseError("JSON number can't be parsed.");
                }
                cval = (cval * 10) + (int)(c - '0');
                c    = this.index < this.endPos ? ((int)this.bytes[this.index++]) &
                       0xff : -1;
                if (c >= '0' && c <= '9')
                {
                    var digits = 2;
                    while (digits < 9 && (c >= '0' && c <= '9'))
                    {
                        cval = (cval * 10) + (int)(c - '0');
                        c    = this.index < this.endPos ?
                               ((int)this.bytes[this.index++]) & 0xff : -1;
                        ++digits;
                    }
                    if (!(c == 'e' || c == 'E' || c == '.' || (c >= '0' && c <=
                                                               '9')))
                    {
                        // All-digit number that's short enough
                        obj = CBORDataUtilities.ParseSmallNumber(cval, this.options);
            #if DEBUG
                        if ((
                                (EDecimal)obj.ToObject(
                                    typeof(EDecimal))).CompareToValue(EDecimal.FromInt32(cval)) !=
                            0)
                        {
                            this.RaiseError(String.Empty + obj);
                        }
            #endif
                        needObj = false;
                    }
                }
                else if (!(c == '-' || c == '+' || c == '.' || c == 'e' || c
                           == 'E'))
                {
                    // Optimize for common case where JSON number
                    // is two digits without sign, decimal point, or exponent
                    obj = CBORDataUtilities.ParseSmallNumber(cval, this.options);
          #if DEBUG
                    if ((
                            (EDecimal)obj.ToObject(
                                typeof(EDecimal))).CompareToValue(EDecimal.FromInt32(cval)) !=
                        0)
                    {
                        this.RaiseError(String.Empty + obj);
                    }
          #endif
                    needObj = false;
                }
            }
            if (needObj)
            {
                while (c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                       c == 'e' || c == 'E')
                {
                    c = this.index < this.endPos ? ((int)this.bytes[this.index++]) &
                        0xff : -1;
                }
                // check if character can validly appear after a JSON number
                if (c != ',' && c != ']' && c != '}' && c != -1 &&
                    c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                {
                    this.RaiseError("Invalid character after JSON number");
                }
                int numberEndIndex = c < 0 ? this.endPos : this.index - 1;
                obj = CBORDataUtilities.ParseJSONNumber(
                    this.bytes,
                    numberStartIndex,
                    numberEndIndex - numberStartIndex,
                    this.options);
        #if DEBUG
                if (this.options.NumberConversion == JSONOptions.ConversionMode.Full &&
                    (
                        (EDecimal)obj.ToObject(
                            typeof(EDecimal))).CompareToValue(EDecimal.FromString(this.bytes,
                                                                                  numberStartIndex,
                                                                                  numberEndIndex - numberStartIndex)) != 0)
                {
                    this.RaiseError(String.Empty + obj);
                }
        #endif
                if (obj == null)
                {
                    string errstr = String.Empty;
                    // errstr = (str.Length <= 100) ? str : (str.Substring(0,
                    // 100) + "...");
                    this.RaiseError("JSON number can't be parsed. " + errstr);
                }
            }
            if (c == -1 || (c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09))
            {
                nextChar[0] = c;
            }
            else
            {
                nextChar[0] = this.SkipWhitespaceJSON();
            }
            return(obj);
        }
Exemplo n.º 4
0
        private CBORObject NextJSONValue(
            int firstChar,
            int[] nextChar,
            int depth)
        {
            string     str;
            int        c   = firstChar;
            CBORObject obj = null;

            if (c < 0)
            {
                this.reader.RaiseError("Unexpected end of data");
            }
            switch (c)
            {
            case '"':
            {
                // Parse a string
                // The tokenizer already checked the string for invalid
                // surrogate pairs, so just call the CBORObject
                // constructor directly
                obj         = CBORObject.FromRaw(this.NextJSONString());
                nextChar[0] = SkipWhitespaceJSON(this.reader);
                return(obj);
            }

            case '{':
            {
                // Parse an object
                obj         = this.ParseJSONObject(depth + 1);
                nextChar[0] = SkipWhitespaceJSON(this.reader);
                return(obj);
            }

            case '[':
            {
                // Parse an array
                obj         = this.ParseJSONArray(depth + 1);
                nextChar[0] = SkipWhitespaceJSON(this.reader);
                return(obj);
            }

            case 't':
            {
                // Parse true
                if (this.reader.ReadChar() != 'r' || this.reader.ReadChar() != 'u' ||
                    this.reader.ReadChar() != 'e')
                {
                    this.reader.RaiseError("Value can't be parsed.");
                }
                nextChar[0] = SkipWhitespaceJSON(this.reader);
                return(CBORObject.True);
            }

            case 'f':
            {
                // Parse false
                if (this.reader.ReadChar() != 'a' || this.reader.ReadChar() != 'l' ||
                    this.reader.ReadChar() != 's' || this.reader.ReadChar() != 'e')
                {
                    this.reader.RaiseError("Value can't be parsed.");
                }
                nextChar[0] = SkipWhitespaceJSON(this.reader);
                return(CBORObject.False);
            }

            case 'n':
            {
                // Parse null
                if (this.reader.ReadChar() != 'u' || this.reader.ReadChar() != 'l' ||
                    this.reader.ReadChar() != 'l')
                {
                    this.reader.RaiseError("Value can't be parsed.");
                }
                nextChar[0] = SkipWhitespaceJSON(this.reader);
                return(CBORObject.Null);
            }

            case '-':
            {
                // Parse a negative number
                var lengthTwo = true;
                c = this.reader.ReadChar();
                if (c < '0' || c > '9')
                {
                    this.reader.RaiseError("JSON number can't be parsed.");
                }
                int           cval   = -(c - '0');
                int           cstart = c;
                StringBuilder sb     = null;
                c = this.reader.ReadChar();
                while (c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                       c == 'e' || c == 'E')
                {
                    if (lengthTwo)
                    {
                        sb = new StringBuilder();
                        sb.Append((char)'-');
                        sb.Append((char)cstart);
                        lengthTwo = false;
                    }
                    sb.Append((char)c);
                    c = this.reader.ReadChar();
                }
                if (lengthTwo)
                {
                    obj = cval == 0 ?
                          CBORDataUtilities.ParseJSONNumber("-0", true, false, true) :
                          CBORObject.FromObject(cval);
                }
                else
                {
                    str = sb.ToString();
                    obj = CBORDataUtilities.ParseJSONNumber(str);
                    if (obj == null)
                    {
                        this.reader.RaiseError("JSON number can't be parsed. " + str);
                    }
                }
                if (c == -1 || (c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09))
                {
                    nextChar[0] = c;
                }
                else
                {
                    nextChar[0] = SkipWhitespaceJSON(this.reader);
                }
                return(obj);
            }

            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {
                // Parse a number
                var           lengthOne = true;
                int           cval      = c - '0';
                int           cstart    = c;
                StringBuilder sb        = null;
                c = this.reader.ReadChar();
                while (c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                       c == 'e' || c == 'E')
                {
                    if (lengthOne)
                    {
                        sb = new StringBuilder();
                        sb.Append((char)cstart);
                        lengthOne = false;
                    }
                    sb.Append((char)c);
                    c = this.reader.ReadChar();
                }
                if (lengthOne)
                {
                    obj = CBORObject.FromObject(cval);
                }
                else
                {
                    str = sb.ToString();
                    obj = CBORDataUtilities.ParseJSONNumber(str);
                    if (obj == null)
                    {
                        this.reader.RaiseError("JSON number can't be parsed. " + str);
                    }
                }
                if (c == -1 || (c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09))
                {
                    nextChar[0] = c;
                }
                else
                {
                    nextChar[0] = SkipWhitespaceJSON(this.reader);
                }
                return(obj);
            }

            default:
                this.reader.RaiseError("Value can't be parsed.");
                break;
            }
            return(null);
        }
Exemplo n.º 5
0
        private CBORObject NextJSONNegativeNumber(
            int[] nextChar)
        {
            // Assumes the last character read was '-'
            CBORObject obj;
            int        numberStartIndex = this.index - 1;
            int        c = this.index < this.endPos ? ((int)this.bytes[this.index++]) &
                           0xff : -1;

            if (c < '0' || c > '9')
            {
                this.RaiseError("JSON number can't be parsed.");
            }
            int cstart = c;

            while (c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                   c == 'e' || c == 'E')
            {
                c = this.index < this.endPos ? ((int)this.bytes[this.index++]) &
                    0xff : -1;
            }
            // check if character can validly appear after a JSON number
            if (c != ',' && c != ']' && c != '}' && c != -1 &&
                c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
            {
                this.RaiseError("Invalid character after JSON number");
            }
            int numberEndIndex = c < 0 ?
                                 this.endPos : this.index - 1;

            if (numberEndIndex - numberStartIndex == 2 && cstart != '0')
            {
                // Negative single digit other than negative zero
                obj = CBORDataUtilities.ParseSmallNumberAsNegative((int)(cstart
                                                                         - '0'),
                                                                   this.options);
            }
            else
            {
                obj = CBORDataUtilities.ParseJSONNumber(
                    this.bytes,
                    numberStartIndex,
                    numberEndIndex - numberStartIndex,
                    this.options);
        #if DEBUG
                if (this.options.NumberConversion == JSONOptions.ConversionMode.Full &&
                    (
                        (EDecimal)obj.ToObject(
                            typeof(EDecimal))).CompareToValue(EDecimal.FromString(this.bytes,
                                                                                  numberStartIndex,
                                                                                  numberEndIndex - numberStartIndex)) != 0)
                {
                    this.RaiseError(String.Empty + obj);
                }
        #endif
                if (obj == null)
                {
                    string errstr = String.Empty;
                    // errstr = (str.Length <= 100) ? str : (str.Substring(0,
                    // 100) + "...");
                    this.RaiseError("JSON number can't be parsed. " + errstr);
                }
            }
            if (c == -1 || (c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09))
            {
                nextChar[0] = c;
            }
            else
            {
                nextChar[0] = this.SkipWhitespaceJSON();
            }
            return(obj);
        }
Exemplo n.º 6
0
        private CBORObject NextJSONNonnegativeNumber(int c, int[] nextChar)
        {
            // Assumes the last character read was a digit
            CBORObject obj              = null;
            int        cval             = c - '0';
            int        cstart           = c;
            int        startIndex       = this.index - 1;
            var        needObj          = true;
            int        numberStartIndex = this.index - 1;

            // DebugUtility.Log("js=" + (jstring));
            c = this.index < this.endPos ? ((int)this.jstring[this.index++]) &
                0xffff : -1;
            if (!(c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                  c == 'e' || c == 'E'))
            {
                // Optimize for common case where JSON number
                // is a single digit without sign or exponent
                obj     = CBORDataUtilities.ParseSmallNumber(cval, this.options);
                needObj = false;
            }
            else if (c >= '0' && c <= '9')
            {
                int csecond = c;
                if (cstart == '0')
                {
                    // Leading zero followed by any digit is not allowed
                    this.RaiseError("JSON number can't be parsed.");
                }
                cval = (cval * 10) + (int)(c - '0');
                c    = this.index < this.endPos ? ((int)this.jstring[this.index++]) : -1;
                if (c >= '0' && c <= '9')
                {
                    var digits = 2;
                    while (digits < 9 && (c >= '0' && c <= '9'))
                    {
                        cval = (cval * 10) + (int)(c - '0');
                        c    = this.index < this.endPos ?
                               ((int)this.jstring[this.index++]) : -1;
                        ++digits;
                    }
                    if (!(c == 'e' || c == 'E' || c == '.' || (c >= '0' && c <=
                                                               '9')))
                    {
                        // All-digit number that's short enough
                        obj     = CBORDataUtilities.ParseSmallNumber(cval, this.options);
                        needObj = false;
                    }
                }
                else if (!(c == '-' || c == '+' || c == '.' || c == 'e' || c
                           == 'E'))
                {
                    // Optimize for common case where JSON number
                    // is two digits without sign, decimal point, or exponent
                    obj     = CBORDataUtilities.ParseSmallNumber(cval, this.options);
                    needObj = false;
                }
            }
            if (needObj)
            {
                // NOTE: Differs from CBORJson2, notably because the whole
                // rest of the string is checked whether the beginning of the rest
                // is a JSON number
                var endIndex = new int[1];
                endIndex[0] = numberStartIndex;
                obj         = CBORDataUtilitiesTextString.ParseJSONNumber(
                    this.jstring,
                    numberStartIndex,
                    this.endPos - numberStartIndex,
                    this.options,
                    endIndex);
                int numberEndIndex = endIndex[0];
                this.index = numberEndIndex >= this.endPos ? this.endPos :
                             (numberEndIndex + 1);
                if (obj == null)
                {
                    int    strlen = numberEndIndex - numberStartIndex;
                    string errstr = this.jstring.Substring(numberStartIndex,
                                                           Math.Min(100, strlen));
                    if (strlen > 100)
                    {
                        errstr += "...";
                    }
                    this.RaiseError("JSON number can't be parsed. " + errstr);
                }
        #if DEBUG
                if (numberEndIndex < numberStartIndex)
                {
                    throw new ArgumentException("numberEndIndex (" + numberEndIndex +
                                                ") is not greater or equal to " + numberStartIndex);
                }
        #endif

                c = numberEndIndex >= this.endPos ? -1 : this.jstring[numberEndIndex];
                // check if character can validly appear after a JSON number
                if (c != ',' && c != ']' && c != '}' && c != -1 &&
                    c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                {
                    this.RaiseError("Invalid character after JSON number");
                }
                // DebugUtility.Log("endIndex="+endIndex[0]+", "+
                // this.jstring.Substring(endIndex[0],
                // Math.Min(20, this.endPos-endIndex[0])));
            }
            if (c == -1 || (c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09))
            {
                nextChar[0] = c;
            }
            else
            {
                nextChar[0] = this.SkipWhitespaceJSON();
            }
            return(obj);
        }
Exemplo n.º 7
0
        private CBORObject NextJSONNegativeNumber(
            int[] nextChar)
        {
            // Assumes the last character read was '-'
            // DebugUtility.Log("js=" + (jstring));
            CBORObject obj;
            int        numberStartIndex = this.index - 1;
            int        c = this.index < this.endPos ? ((int)this.jstring[this.index++]) &
                           0xffff : -1;

            if (c < '0' || c > '9')
            {
                this.RaiseError("JSON number can't be parsed.");
            }
            if (this.index < this.endPos && c != '0')
            {
                // Check for negative single-digit
                int c2 = ((int)this.jstring[this.index]) & 0xffff;
                if (c2 == ',' || c2 == ']' || c2 == '}')
                {
                    ++this.index;
                    obj = CBORDataUtilities.ParseSmallNumberAsNegative(
                        c - '0',
                        this.options);
                    nextChar[0] = c2;
                    return(obj);
                }
                else if (c2 == 0x20 || c2 == 0x0a || c2 == 0x0d || c2 == 0x09)
                {
                    ++this.index;
                    obj = CBORDataUtilities.ParseSmallNumberAsNegative(
                        c - '0',
                        this.options);
                    nextChar[0] = this.SkipWhitespaceJSON();
                    return(obj);
                }
            }
            // NOTE: Differs from CBORJson2, notably because the whole
            // rest of the string is checked whether the beginning of the rest
            // is a JSON number
            var endIndex = new int[1];

            endIndex[0] = numberStartIndex;
            obj         = CBORDataUtilitiesTextString.ParseJSONNumber(
                this.jstring,
                numberStartIndex,
                this.endPos - numberStartIndex,
                this.options,
                endIndex);
            int numberEndIndex = endIndex[0];

            this.index = numberEndIndex >= this.endPos ? this.endPos :
                         (numberEndIndex + 1);
            if (obj == null)
            {
                int    strlen = numberEndIndex - numberStartIndex;
                string errstr = this.jstring.Substring(numberStartIndex,
                                                       Math.Min(100, strlen));
                if (strlen > 100)
                {
                    errstr += "...";
                }
                this.RaiseError("JSON number can't be parsed. " + errstr);
            }
      #if DEBUG
            if (numberEndIndex < numberStartIndex)
            {
                throw new ArgumentException("numberEndIndex (" + numberEndIndex +
                                            ") is not greater or equal to " + numberStartIndex);
            }
      #endif
            c = numberEndIndex >= this.endPos ? -1 : this.jstring[numberEndIndex];
            // check if character can validly appear after a JSON number
            if (c != ',' && c != ']' && c != '}' && c != -1 &&
                c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
            {
                this.RaiseError("Invalid character after JSON number");
            }
            // DebugUtility.Log("endIndex="+endIndex[0]+", "+
            // this.jstring.Substring(endIndex[0],
            // Math.Min(20, this.endPos-endIndex[0])));
            if (c == -1 || (c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09))
            {
                nextChar[0] = c;
            }
            else
            {
                nextChar[0] = this.SkipWhitespaceJSON();
            }
            return(obj);
        }
        private CBORObject NextJSONNonnegativeNumber(int c, int[] nextChar)
        {
            // Assumes the last character read was a digit
            CBORObject obj = null;
            string     str;
            int        cval             = c - '0';
            int        cstart           = c;
            int        startIndex       = this.index - 1;
            var        needObj          = true;
            int        numberStartIndex = this.index - 1;

            c = this.index < this.endPos ? ((int)this.bytes[this.index++]) &
                0xff : -1;
            if (!(c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                  c == 'e' || c == 'E'))
            {
                // Optimize for common case where JSON number
                // is a single digit without sign or exponent
                obj     = CBORDataUtilities.ParseSmallNumber(cval, this.options);
                needObj = false;
            }
            else if (c >= '0' && c <= '9')
            {
                int csecond = c;
                if (cstart == '0')
                {
                    // Leading zero followed by any digit is not allowed
                    this.RaiseError("JSON number can't be parsed.");
                }
                cval = (cval * 10) + (int)(c - '0');
                c    = this.index < this.endPos ? ((int)this.bytes[this.index++]) &
                       0xff : -1;
                if (c >= '0' && c <= '9')
                {
                    var digits = 2;
                    while (digits < 9 && (c >= '0' && c <= '9'))
                    {
                        cval = (cval * 10) + (int)(c - '0');
                        c    = this.index < this.endPos ?
                               ((int)this.bytes[this.index++]) & 0xff : -1;
                        ++digits;
                    }
                    if (!(c == 'e' || c == 'E' || c == '.' || (c >= '0' && c <=
                                                               '9')))
                    {
                        // All-digit number that's short enough
                        obj     = CBORDataUtilities.ParseSmallNumber(cval, this.options);
                        needObj = false;
                    }
                }
                else if (!(c == '-' || c == '+' || c == '.' || c == 'e' || c
                           == 'E'))
                {
                    // Optimize for common case where JSON number
                    // is two digits without sign, decimal point, or exponent
                    obj     = CBORDataUtilities.ParseSmallNumber(cval, this.options);
                    needObj = false;
                }
            }
            if (needObj)
            {
                while (c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                       c == 'e' || c == 'E')
                {
                    c = this.index < this.endPos ? ((int)this.bytes[this.index++]) &
                        0xff : -1;
                }
                // check if character can validly appear after a JSON number
                if (c != ',' && c != ']' && c != '}' && c != -1 &&
                    c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                {
                    this.RaiseError("Invalid character after JSON number");
                }
                int numberEndIndex = c < 0 ? this.endPos : this.index - 1;
                var ssb            = new StringBuilder(numberEndIndex - startIndex);
                int ki;
                for (ki = startIndex; ki < numberEndIndex; ++ki)
                {
                    ssb.Append((char)(((int)this.bytes[ki]) & 0xff));
                }
                str = ssb.ToString();
                obj = CBORDataUtilities.ParseJSONNumber(str, this.options);
                if (obj == null)
                {
                    string errstr = (str.Length <= 100) ? str : (str.Substring(0,
                                                                               100) + "...");
                    this.RaiseError("JSON number can't be parsed. " + errstr);
                }
            }
            if (c == -1 || (c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09))
            {
                nextChar[0] = c;
            }
            else
            {
                nextChar[0] = this.SkipWhitespaceJSON();
            }
            return(obj);
        }
        private CBORObject NextJSONNegativeNumber(
            int[] nextChar)
        {
            // Assumes the last character read was '-'
            CBORObject obj;
            int        numberStartIndex = this.index - 1;
            int        c = this.index < this.endPos ? ((int)this.bytes[this.index++]) &
                           0xff : -1;

            if (c < '0' || c > '9')
            {
                this.RaiseError("JSON number can't be parsed.");
            }
            int cstart = c;

            while (c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') ||
                   c == 'e' || c == 'E')
            {
                c = this.index < this.endPos ? ((int)this.bytes[this.index++]) &
                    0xff : -1;
            }
            // check if character can validly appear after a JSON number
            if (c != ',' && c != ']' && c != '}' && c != -1 &&
                c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
            {
                this.RaiseError("Invalid character after JSON number");
            }
            int numberEndIndex = c < 0 ?
                                 this.endPos : this.index - 1;

            if (numberEndIndex - numberStartIndex == 2 && cstart != '0')
            {
                // Negative single digit other than negative zero
                obj = CBORDataUtilities.ParseSmallNumberAsNegative((int)(cstart
                                                                         - '0'),
                                                                   this.options);
            }
            else
            {
                var ssb = new StringBuilder(numberEndIndex - numberStartIndex);
                int ki;
                for (ki = numberStartIndex; ki < numberEndIndex; ++ki)
                {
                    ssb.Append((char)(((int)this.bytes[ki]) & 0xff));
                }
                string str = ssb.ToString();
                obj = CBORDataUtilities.ParseJSONNumber(str, this.options);
                if (obj == null)
                {
                    string errstr = (str.Length <= 100) ? str : (str.Substring(0,
                                                                               100) + "...");
                    this.RaiseError("JSON number can't be parsed. " + errstr);
                }
            }
            if (c == -1 || (c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09))
            {
                nextChar[0] = c;
            }
            else
            {
                nextChar[0] = this.SkipWhitespaceJSON();
            }
            return(obj);
        }