Example #1
0
 /// <summary>Parses a number whose format follows the JSON
 /// specification (RFC 8259) and converts that number to a CBOR
 /// object.</summary>
 /// <param name='str'>A text string to parse as a JSON number.</param>
 /// <param name='offset'>An index, starting at 0, showing where the
 /// desired portion of <paramref name='str'/> begins.</param>
 /// <param name='count'>The length, in code units, of the desired
 /// portion of <paramref name='str'/> (but not more than <paramref
 /// name='str'/> 's length).</param>
 /// <param name='options'>An object containing options to control how
 /// JSON numbers are decoded to CBOR objects. Can be null, in which
 /// case a JSONOptions object with all default properties is used
 /// instead.</param>
 /// <returns>A CBOR object that represents the parsed number. Returns
 /// null if the parsing fails, including if the string is null or empty
 /// or <paramref name='count'/> is 0 or less.</returns>
 /// <exception cref='ArgumentNullException'>The parameter <paramref
 /// name='str'/> is null.</exception>
 /// <exception cref='ArgumentException'>Unsupported conversion
 /// kind.</exception>
 /// <remarks>Roughly speaking, a valid JSON number consists of an
 /// optional minus sign, one or more basic digits (starting with 1 to 9
 /// unless there is only one digit and that digit is 0), an optional
 /// decimal point (".", full stop) with one or more basic digits, and
 /// an optional letter E or e with an optional plus or minus sign and
 /// one or more basic digits (the exponent). A text string representing
 /// a valid JSON number is not allowed to contain white space
 /// characters, including spaces.</remarks>
 public static CBORObject ParseJSONNumber(
     string str,
     int offset,
     int count,
     JSONOptions options)
 {
     return(CBORDataUtilitiesTextString.ParseJSONNumber(
                str,
                offset,
                count,
                options,
                null));
 }
Example #2
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);
        }
Example #3
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);
        }