FromObject() public static method

public static FromObject ( decimal value ) : CBORObject
value decimal
return CBORObject
Esempio n. 1
0
        public static CBORObject FromArray(
            Object arrObj,
            PODOptions options)
        {
            var arr  = (Array)arrObj;
            int rank = arr.Rank;

            if (rank == 0)
            {
                return(CBORObject.NewArray());
            }
            CBORObject obj = null;

            if (rank == 1)
            {
                // Most common case: the array is one-dimensional
                obj = CBORObject.NewArray();
                int len = arr.GetLength(0);
                for (var i = 0; i < len; ++i)
                {
                    obj.Add(
                        CBORObject.FromObject(
                            arr.GetValue(i),
                            options));
                }
                return(obj);
            }
            var index      = new int[rank];
            var dimensions = new int[rank];

            for (var i = 0; i < rank; ++i)
            {
                dimensions[i] = arr.GetLength(i);
            }
            if (!FirstElement(index, dimensions))
            {
                return(obj);
            }
            obj = BuildCBORArray(dimensions);
            do
            {
                CBORObject o = CBORObject.FromObject(
                    arr.GetValue(index),
                    options);
                SetCBORObject(obj, index, o);
            } while (NextElement(index, dimensions));
            return(obj);
        }
Esempio n. 2
0
        private static CBORObject FromObjectAndInnerTags(
            object objectValue,
            CBORObject objectWithTags)
        {
            CBORObject newObject = CBORObject.FromObject(objectValue);

            if (!objectWithTags.IsTagged)
            {
                return(newObject);
            }
            objectWithTags = objectWithTags.UntagOne();
            if (!objectWithTags.IsTagged)
            {
                return(newObject);
            }
            EInteger[] tags = objectWithTags.GetAllTags();
            for (int i = tags.Length - 1; i >= 0; --i)
            {
                newObject = CBORObject.FromObjectAndTag(newObject, tags[i]);
            }
            return(newObject);
        }
Esempio n. 3
0
        internal static CBORObject ParseSmallNumber(int digit, JSONOptions
                                                    options)
        {
#if DEBUG
            if (digit < 0)
            {
                throw new ArgumentException("digit (" + digit + ") is not greater" +
                                            "\u0020or equal to 0");
            }
#endif

            if (options != null && options.NumberConversion ==
                JSONOptions.ConversionMode.Double)
            {
                return(CBORObject.FromObject((double)digit));
            }
            else
            {
                // NOTE: Assumes digit is nonnegative, so PreserveNegativeZeros is irrelevant
                return(CBORObject.FromObject(digit));
            }
        }
Esempio n. 4
0
        internal static CBORObject ConvertToDecimalFrac(
            CBORObject o,
            bool isDecimal,
            bool extended)
        {
            if (o.Type != CBORType.Array)
            {
                throw new CBORException("Big fraction must be an array");
            }
            if (o.Count != 2)
            {
                throw new CBORException("Big fraction requires exactly 2 items");
            }
            if (!o[0].IsIntegral)
            {
                throw new CBORException("Exponent is not an integer");
            }
            if (!o[1].IsIntegral)
            {
                throw new CBORException("Mantissa is not an integer");
            }
            EInteger exponent = o[0].AsEInteger();
            EInteger mantissa = o[1].AsEInteger();

            if (exponent.GetSignedBitLength() > 64 && !extended)
            {
                throw new CBORException("Exponent is too big");
            }
            if (exponent.IsZero)
            {
                // Exponent is 0, so return mantissa instead
                return(CBORObject.FromObject(mantissa));
            }
            // NOTE: Discards tags. See comment in CBORTag2.
            return(isDecimal ?
                   CBORObject.FromObject(EDecimal.Create(mantissa, exponent)) :
                   CBORObject.FromObject(EFloat.Create(mantissa, exponent)));
        }
Esempio n. 5
0
        public CBORObject GetString(long smallIndex)
        {
            if (smallIndex < 0)
            {
                throw new CBORException("Unexpected index");
            }
            if (smallIndex > Int32.MaxValue)
            {
                throw new CBORException("Index " + smallIndex +
                                        " is bigger than supported ");
            }
            var index = (int)smallIndex;
            List <CBORObject> lastList = this.stack[this.stack.Count - 1];

            if (index >= lastList.Count)
            {
                throw new CBORException("Index " + index + " is not valid");
            }
            CBORObject ret = lastList[index];

            // Byte strings are mutable, so make a copy
            return((ret.Type == CBORType.ByteString) ?
                   CBORObject.FromObject(ret.GetByteString()) : ret);
        }
Esempio n. 6
0
        public CBORObject GetString(EInteger bigIndex)
        {
            if (bigIndex.Sign < 0)
            {
                throw new CBORException("Unexpected index");
            }
            if (!bigIndex.CanFitInInt32())
            {
                throw new CBORException("Index " + bigIndex +
                                        " is bigger than supported ");
            }
            var index = (int)bigIndex;
            List <CBORObject> lastList = this.stack[this.stack.Count - 1];

            if (index >= lastList.Count)
            {
                throw new CBORException("Index " + index + " is not valid");
            }
            CBORObject ret = lastList[index];

            // Byte strings are mutable, so make a copy
            return((ret.Type == CBORType.ByteString) ?
                   CBORObject.FromObject(ret.GetByteString()) : ret);
        }
Esempio n. 7
0
        public static CBORObject Remainder(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }
            if (b == null)
            {
                throw new ArgumentNullException("b");
            }
            if (a.Type != CBORType.Number)
            {
                throw new ArgumentException("a.Type (" + a.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            if (b.Type != CBORType.Number)
            {
                throw new ArgumentException("b.Type (" + b.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            object objA  = a.ThisItem;
            object objB  = b.ThisItem;
            int    typeA = a.ItemType;
            int    typeB = b.ItemType;

            if (typeA == CBORObject.CBORObjectTypeInteger && typeB ==
                CBORObject.CBORObjectTypeInteger)
            {
                var valueA = (long)objA;
                var valueB = (long)objB;
                return((valueA == Int64.MinValue && valueB == -1) ?
                       CBORObject.FromObject(0) : CBORObject.FromObject(valueA % valueB));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedRational ||
                typeB == CBORObject.CBORObjectTypeExtendedRational)
            {
                ERational e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(e1.Remainder(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedDecimal ||
                typeB == CBORObject.CBORObjectTypeExtendedDecimal)
            {
                EDecimal e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA);
                EDecimal e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB);
                return(CBORObject.FromObject(e1.Remainder(e2, null)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB ==
                CBORObject.CBORObjectTypeExtendedFloat ||
                typeA == CBORObject.CBORObjectTypeDouble || typeB ==
                CBORObject.CBORObjectTypeDouble ||
                typeA == CBORObject.CBORObjectTypeSingle || typeB ==
                CBORObject.CBORObjectTypeSingle)
            {
                EFloat e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA);
                EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB);
                return(CBORObject.FromObject(e1.Remainder(e2, null)));
            }
            else
            {
                EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA);
                EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB);
                return(CBORObject.FromObject(b1 % (EInteger)b2));
            }
        }
Esempio n. 8
0
        public static CBORObject Divide(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }
            if (b == null)
            {
                throw new ArgumentNullException("b");
            }
            if (a.Type != CBORType.Number)
            {
                throw new ArgumentException("a.Type (" + a.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            if (b.Type != CBORType.Number)
            {
                throw new ArgumentException("b.Type (" + b.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            object objA  = a.ThisItem;
            object objB  = b.ThisItem;
            int    typeA = a.ItemType;
            int    typeB = b.ItemType;

            if (typeA == CBORObject.CBORObjectTypeInteger && typeB ==
                CBORObject.CBORObjectTypeInteger)
            {
                var valueA = (long)objA;
                var valueB = (long)objB;
                if (valueB == 0)
                {
                    return((valueA == 0) ? CBORObject.NaN : ((valueA < 0) ?
                                                             CBORObject.NegativeInfinity : CBORObject.PositiveInfinity));
                }
                if (valueA == Int64.MinValue && valueB == -1)
                {
                    return(CBORObject.FromObject(valueA).Negate());
                }
                long quo = valueA / valueB;
                long rem = valueA - (quo * valueB);
                return((rem == 0) ? CBORObject.FromObject(quo) :
                       CBORObject.FromObject(
                           ERational.Create(
                               (EInteger)valueA,
                               (EInteger)valueB)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedRational ||
                typeB == CBORObject.CBORObjectTypeExtendedRational)
            {
                ERational e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(e1.Divide(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedDecimal ||
                typeB == CBORObject.CBORObjectTypeExtendedDecimal)
            {
                EDecimal e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA);
                EDecimal e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB);
                if (e1.IsZero && e2.IsZero)
                {
                    return(CBORObject.NaN);
                }
                EDecimal eret = e1.Divide(e2, null);
                // If either operand is infinity or NaN, the result
                // is already exact. Likewise if the result is a finite number.
                if (!e1.IsFinite || !e2.IsFinite || eret.IsFinite)
                {
                    return(CBORObject.FromObject(eret));
                }
                ERational er1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational er2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(er1.Divide(er2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB ==
                CBORObject.CBORObjectTypeExtendedFloat ||
                typeA == CBORObject.CBORObjectTypeDouble || typeB ==
                CBORObject.CBORObjectTypeDouble ||
                typeA == CBORObject.CBORObjectTypeSingle || typeB ==
                CBORObject.CBORObjectTypeSingle)
            {
                EFloat e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA);
                EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB);
                if (e1.IsZero && e2.IsZero)
                {
                    return(CBORObject.NaN);
                }
                EFloat eret = e1.Divide(e2, null);
                // If either operand is infinity or NaN, the result
                // is already exact. Likewise if the result is a finite number.
                if (!e1.IsFinite || !e2.IsFinite || eret.IsFinite)
                {
                    return(CBORObject.FromObject(eret));
                }
                ERational er1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational er2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(er1.Divide(er2)));
            }
            else
            {
                EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA);
                EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB);
                if (b2.IsZero)
                {
                    return(b1.IsZero ? CBORObject.NaN : ((b1.Sign < 0) ?
                                                         CBORObject.NegativeInfinity : CBORObject.PositiveInfinity));
                }
                EInteger bigrem;
                EInteger bigquo;
                {
                    EInteger[] divrem = b1.DivRem(b2);
                    bigquo = divrem[0];
                    bigrem = divrem[1];
                }
                return(bigrem.IsZero ? CBORObject.FromObject(bigquo) :
                       CBORObject.FromObject(ERational.Create(b1, b2)));
            }
        }
Esempio n. 9
0
        public static CBORObject Multiply(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }
            if (b == null)
            {
                throw new ArgumentNullException("b");
            }
            if (a.Type != CBORType.Number)
            {
                throw new ArgumentException("a.Type (" + a.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            if (b.Type != CBORType.Number)
            {
                throw new ArgumentException("b.Type (" + b.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            object objA  = a.ThisItem;
            object objB  = b.ThisItem;
            int    typeA = a.ItemType;
            int    typeB = b.ItemType;

            if (typeA == CBORObject.CBORObjectTypeInteger && typeB ==
                CBORObject.CBORObjectTypeInteger)
            {
                var  valueA = (long)objA;
                var  valueB = (long)objB;
                bool apos   = valueA > 0L;
                bool bpos   = valueB > 0L;
                if (
                    (apos && ((!bpos && (Int64.MinValue / valueA) > valueB) ||
                              (bpos && valueA > (Int64.MaxValue / valueB)))) ||
                    (!apos && ((!bpos && valueA != 0L &&
                                (Int64.MaxValue / valueA) > valueB) ||
                               (bpos && valueA < (Int64.MinValue / valueB)))))
                {
                    // would overflow, convert to EInteger
                    var bvalueA = (EInteger)valueA;
                    var bvalueB = (EInteger)valueB;
                    return(CBORObject.FromObject(bvalueA * (EInteger)bvalueB));
                }
                return(CBORObject.FromObject(valueA * valueB));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedRational ||
                typeB == CBORObject.CBORObjectTypeExtendedRational)
            {
                ERational e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(e1.Multiply(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedDecimal ||
                typeB == CBORObject.CBORObjectTypeExtendedDecimal)
            {
                EDecimal e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA);
                EDecimal e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB);
                return(CBORObject.FromObject(e1.Multiply(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB ==
                CBORObject.CBORObjectTypeExtendedFloat ||
                typeA == CBORObject.CBORObjectTypeDouble || typeB ==
                CBORObject.CBORObjectTypeDouble ||
                typeA == CBORObject.CBORObjectTypeSingle || typeB ==
                CBORObject.CBORObjectTypeSingle)
            {
                EFloat e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA);
                EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB);
                return(CBORObject.FromObject(e1.Multiply(e2)));
            }
            else
            {
                EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA);
                EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB);
                return(CBORObject.FromObject(b1 * (EInteger)b2));
            }
        }
Esempio n. 10
0
        internal static CBORObject ParseJSONNumber(
            string chars,
            int offset,
            int count,
            JSONOptions options,
            int[] endOfNumber)
        {
            if (chars == null || chars.Length == 0 || count <= 0)
            {
                return(null);
            }
            if (offset < 0 || offset > chars.Length)
            {
                return(null);
            }
            if (count > chars.Length || chars.Length - offset < count)
            {
                return(null);
            }
            JSONOptions opt = options ?? CBORDataUtilities.DefaultOptions;
            bool        preserveNegativeZero = options.PreserveNegativeZero;

            JSONOptions.ConversionMode kind = options.NumberConversion;
            int endPos        = offset + count;
            int initialOffset = offset;
            var negative      = false;

            if (chars[initialOffset] == '-')
            {
                ++offset;
                negative = true;
            }
            int numOffset              = offset;
            var haveDecimalPoint       = false;
            var haveDigits             = false;
            var haveDigitsAfterDecimal = false;
            var haveExponent           = false;
            int i = offset;
            var decimalPointPos = -1;
            // Check syntax
            int k = i;

            if (endPos - 1 > k && chars[k] == '0' && chars[k + 1] >= '0' &&
                chars[k + 1] <= '9')
            {
                if (endOfNumber != null)
                {
                    endOfNumber[0] = k + 2;
                }
                return(null);
            }
            for (; k < endPos; ++k)
            {
                char c = chars[k];
                if (c >= '0' && c <= '9')
                {
                    haveDigits              = true;
                    haveDigitsAfterDecimal |= haveDecimalPoint;
                }
                else if (c == '.')
                {
                    if (!haveDigits || haveDecimalPoint)
                    {
                        // no digits before the decimal point,
                        // or decimal point already seen
                        if (endOfNumber != null)
                        {
                            endOfNumber[0] = k;
                        }
                        return(null);
                    }
                    haveDecimalPoint = true;
                    decimalPointPos  = k;
                }
                else if (c == 'E' || c == 'e')
                {
                    ++k;
                    haveExponent = true;
                    break;
                }
                else
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                        // Check if character can validly appear after a JSON number
                        if (c != ',' && c != ']' && c != '}' &&
                            c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                        {
                            return(null);
                        }
                        else
                        {
                            endPos = k;
                            break;
                        }
                    }
                    return(null);
                }
            }
            if (!haveDigits || (haveDecimalPoint && !haveDigitsAfterDecimal))
            {
                if (endOfNumber != null)
                {
                    endOfNumber[0] = k;
                }
                return(null);
            }
            var exponentPos = -1;
            var negativeExp = false;

            if (haveExponent)
            {
                haveDigits = false;
                if (k == endPos)
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                    }
                    return(null);
                }
                char c = chars[k];
                if (c == '+')
                {
                    ++k;
                }
                else if (c == '-')
                {
                    negativeExp = true;
                    ++k;
                }
                for (; k < endPos; ++k)
                {
                    c = chars[k];
                    if (c >= '0' && c <= '9')
                    {
                        if (exponentPos < 0 && c != '0')
                        {
                            exponentPos = k;
                        }
                        haveDigits = true;
                    }
                    else if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                        // Check if character can validly appear after a JSON number
                        if (c != ',' && c != ']' && c != '}' &&
                            c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                        {
                            return(null);
                        }
                        else
                        {
                            endPos = k;
                            break;
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }
                if (!haveDigits)
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                    }
                    return(null);
                }
            }
            if (endOfNumber != null)
            {
                endOfNumber[0] = endPos;
            }
            if (exponentPos >= 0 && endPos - exponentPos > 20)
            {
                // Exponent too high for precision to overcome (which
                // has a length no bigger than Int32.MaxValue, which is 10 digits
                // long)
                if (negativeExp)
                {
                    // underflow
                    if (kind == JSONOptions.ConversionMode.Double ||
                        kind == JSONOptions.ConversionMode.IntOrFloat)
                    {
                        if (!negative)
                        {
                            return(CBORObject.FromFloatingPointBits(0, 2));
                        }
                        else
                        {
                            return(CBORObject.FromFloatingPointBits(0x8000, 2));
                        }
                    }
                    else if (kind ==
                             JSONOptions.ConversionMode.IntOrFloatFromDouble)
                    {
                        return(CBORObject.FromObject(0));
                    }
                }
                else
                {
                    // overflow
                    if (kind == JSONOptions.ConversionMode.Double ||
                        kind == JSONOptions.ConversionMode.IntOrFloatFromDouble ||
                        kind == JSONOptions.ConversionMode.IntOrFloat)
                    {
                        return(CBORObject.FromFloatingPointBits(
                                   negative ? DoubleNegInfinity : DoublePosInfinity,
                                   8));
                    }
                    else if (kind == JSONOptions.ConversionMode.Decimal128)
                    {
                        return(CBORObject.FromObject(negative ?
                                                     EDecimal.NegativeInfinity : EDecimal.PositiveInfinity));
                    }
                }
            }
            if (!haveExponent && !haveDecimalPoint &&
                (endPos - numOffset) <= 16)
            {
                // Very common case of all-digit JSON number strings
                // less than 2^53 (with or without number sign)
                long v  = 0L;
                int  vi = numOffset;
                for (; vi < endPos; ++vi)
                {
                    v = (v * 10) + (int)(chars[vi] - '0');
                }
                if ((v != 0 || !negative) && v < (1L << 53) - 1)
                {
                    if (negative)
                    {
                        v = -v;
                    }
                    if (kind == JSONOptions.ConversionMode.Double)
                    {
                        return(CBORObject.FromFloatingPointBits(EFloat.FromInt64(v).ToDoubleBits(), 8));
                    }
                    else if (kind == JSONOptions.ConversionMode.Decimal128)
                    {
                        return(CBORObject.FromObject(EDecimal.FromInt64(v)));
                    }
                    else
                    {
                        return(CBORObject.FromObject(v));
                    }
                }
            }
            if (kind == JSONOptions.ConversionMode.Full)
            {
                if (!haveDecimalPoint && !haveExponent)
                {
                    EInteger ei = EInteger.FromSubstring(chars, initialOffset, endPos);
                    if (preserveNegativeZero && ei.IsZero && negative)
                    {
                        // TODO: In next major version, change to EDecimal.NegativeZero
                        return(CBORObject.FromFloatingPointBits(0x8000, 2));
                    }
                    return(CBORObject.FromObject(ei));
                }
                if (!haveExponent && haveDecimalPoint)
                {
                    // No more than 18 digits plus one decimal point (which
                    // should fit a long)
                    long lv         = 0L;
                    int  expo       = -(endPos - (decimalPointPos + 1));
                    int  vi         = numOffset;
                    var  digitCount = 0;
                    for (; vi < decimalPointPos; ++vi)
                    {
                        if (digitCount < 0 || digitCount >= 18)
                        {
                            digitCount = -1;
                            break;
                        }
                        else if (digitCount > 0 || chars[vi] != '0')
                        {
                            ++digitCount;
                        }
                        lv = checked ((lv * 10) + (int)(chars[vi] - '0'));
                    }
                    for (vi = decimalPointPos + 1; vi < endPos; ++vi)
                    {
                        if (digitCount < 0 || digitCount >= 18)
                        {
                            digitCount = -1;
                            break;
                        }
                        else if (digitCount > 0 || chars[vi] != '0')
                        {
                            ++digitCount;
                        }
                        lv = checked ((lv * 10) + (int)(chars[vi] - '0'));
                    }
                    if (negative)
                    {
                        lv = -lv;
                    }
                    if (digitCount >= 0 && (!negative || lv != 0))
                    {
                        if (expo == 0)
                        {
                            return(CBORObject.FromObject(lv));
                        }
                        else
                        {
                            CBORObject cbor = CBORObject.FromArrayBackedObject(
                                new CBORObject[] {
                                CBORObject.FromObject(expo),
                                CBORObject.FromObject(lv),
                            });
                            return(cbor.WithTag(4));
                        }
                    }
                }
                // DebugUtility.Log("convfull " + chars.Substring(initialOffset, endPos -
                // initialOffset));
                EDecimal ed = EDecimal.FromString(
                    chars,
                    initialOffset,
                    endPos - initialOffset);
                if (ed.IsZero && negative)
                {
                    if (ed.Exponent.IsZero)
                    {
                        // TODO: In next major version, use EDecimal
                        // for preserveNegativeZero
                        return(preserveNegativeZero ?
                               CBORObject.FromFloatingPointBits(0x8000, 2) :
                               CBORObject.FromObject(0));
                    }
                    else if (!preserveNegativeZero)
                    {
                        return(CBORObject.FromObject(ed.Negate()));
                    }
                    else
                    {
                        return(CBORObject.FromObject(ed));
                    }
                }
                else
                {
                    return(ed.Exponent.IsZero ? CBORObject.FromObject(ed.Mantissa) :
                           CBORObject.FromObject(ed));
                }
            }
            else if (kind == JSONOptions.ConversionMode.Double)
            {
                EFloat ef = EFloat.FromString(
                    chars,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Binary64);
                long lb = ef.ToDoubleBits();
                if (!preserveNegativeZero && (lb == 1L << 63 || lb == 0L))
                {
                    lb = 0L;
                }
                return(CBORObject.FromFloatingPointBits(lb, 8));
            }
            else if (kind == JSONOptions.ConversionMode.Decimal128)
            {
                EDecimal ed = EDecimal.FromString(
                    chars,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Decimal128);
                if (!preserveNegativeZero && ed.IsNegative && ed.IsZero)
                {
                    ed = ed.Negate();
                }
                return(CBORObject.FromObject(ed));
            }
            else if (kind == JSONOptions.ConversionMode.IntOrFloatFromDouble)
            {
                EFloat ef = EFloat.FromString(
                    chars,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Binary64);
                long lb = ef.ToDoubleBits();
                return((!CBORUtilities.IsBeyondSafeRange(lb) &&
                        CBORUtilities.IsIntegerValue(lb)) ?
                       CBORObject.FromObject(CBORUtilities.GetIntegerValue(lb)) :
                       CBORObject.FromFloatingPointBits(lb, 8));
            }
            else if (kind == JSONOptions.ConversionMode.IntOrFloat)
            {
                EContext ctx = EContext.Binary64.WithBlankFlags();
                EFloat   ef  = EFloat.FromString(
                    chars,
                    initialOffset,
                    endPos - initialOffset,
                    ctx);
                long lb = ef.ToDoubleBits();
                if ((ctx.Flags & EContext.FlagInexact) != 0)
                {
                    // Inexact conversion to double, meaning that the string doesn't
                    // represent an integer in [-(2^53)+1, 2^53), which is representable
                    // exactly as double, so treat as ConversionMode.Double
                    if (!preserveNegativeZero && (lb == 1L << 63 || lb == 0L))
                    {
                        lb = 0L;
                    }
                    return(CBORObject.FromFloatingPointBits(lb, 8));
                }
                else
                {
                    // Exact conversion; treat as ConversionMode.IntToFloatFromDouble
                    return((!CBORUtilities.IsBeyondSafeRange(lb) &&
                            CBORUtilities.IsIntegerValue(lb)) ?
                           CBORObject.FromObject(CBORUtilities.GetIntegerValue(lb)) :
                           CBORObject.FromFloatingPointBits(lb, 8));
                }
            }
            else
            {
                throw new ArgumentException("Unsupported conversion kind.");
            }
        }
Esempio n. 11
0
 /// <summary>Converts this object's value to a CBOR object.</summary>
 /// <returns>A CBOR object that stores this object's value.</returns>
 public CBORObject ToCBORObject()
 {
     return(CBORObject.FromObject(this.value));
 }
Esempio n. 12
0
        internal static CBORObject ParseJSONNumber(
            string str,
            int offset,
            int count,
            JSONOptions options,
            int[] endOfNumber)
        {
            if (String.IsNullOrEmpty(str) || count <= 0)
            {
                return(null);
            }
            if (offset < 0 || offset > str.Length)
            {
                return(null);
            }
            if (count > str.Length || str.Length - offset < count)
            {
                return(null);
            }
            JSONOptions opt = options ?? DefaultOptions;
            bool        preserveNegativeZero = options.PreserveNegativeZero;

            JSONOptions.ConversionMode kind = options.NumberConversion;
            int endPos        = offset + count;
            int initialOffset = offset;
            var negative      = false;

            if (str[initialOffset] == '-')
            {
                ++offset;
                negative = true;
            }
            int numOffset              = offset;
            var haveDecimalPoint       = false;
            var haveDigits             = false;
            var haveDigitsAfterDecimal = false;
            var haveExponent           = false;
            int i = offset;
            var decimalPointPos = -1;
            // Check syntax
            int k = i;

            if (endPos - 1 > k && str[k] == '0' && str[k + 1] >= '0' &&
                str[k + 1] <= '9')
            {
                if (endOfNumber != null)
                {
                    endOfNumber[0] = k + 2;
                }
                return(null);
            }
            for (; k < endPos; ++k)
            {
                char c = str[k];
                if (c >= '0' && c <= '9')
                {
                    haveDigits              = true;
                    haveDigitsAfterDecimal |= haveDecimalPoint;
                }
                else if (c == '.')
                {
                    if (!haveDigits || haveDecimalPoint)
                    {
                        // no digits before the decimal point,
                        // or decimal point already seen
                        if (endOfNumber != null)
                        {
                            endOfNumber[0] = k;
                        }
                        return(null);
                    }
                    haveDecimalPoint = true;
                    decimalPointPos  = k;
                }
                else if (c == 'E' || c == 'e')
                {
                    ++k;
                    haveExponent = true;
                    break;
                }
                else
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                        // Check if character can validly appear after a JSON number
                        if (c != ',' && c != ']' && c != '}' &&
                            c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                        {
                            return(null);
                        }
                        else
                        {
                            endPos = k;
                            break;
                        }
                    }
                    return(null);
                }
            }
            if (!haveDigits || (haveDecimalPoint && !haveDigitsAfterDecimal))
            {
                if (endOfNumber != null)
                {
                    endOfNumber[0] = k;
                }
                return(null);
            }
            if (haveExponent)
            {
                haveDigits = false;
                if (k == endPos)
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                    }
                    return(null);
                }
                char c = str[k];
                if (c == '+' || c == '-')
                {
                    ++k;
                }
                for (; k < endPos; ++k)
                {
                    c = str[k];
                    if (c >= '0' && c <= '9')
                    {
                        haveDigits = true;
                    }
                    else if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                        // Check if character can validly appear after a JSON number
                        if (c != ',' && c != ']' && c != '}' &&
                            c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)
                        {
                            return(null);
                        }
                        else
                        {
                            endPos = k;
                            break;
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }
                if (!haveDigits)
                {
                    if (endOfNumber != null)
                    {
                        endOfNumber[0] = k;
                    }
                    return(null);
                }
            }
            if (endOfNumber != null)
            {
                endOfNumber[0] = endPos;
            }
            if (!haveExponent && !haveDecimalPoint &&
                (endPos - numOffset) <= 16)
            {
                // Very common case of all-digit JSON number strings
                // less than 2^53 (with or without number sign)
                long v  = 0L;
                int  vi = numOffset;
                for (; vi < endPos; ++vi)
                {
                    v = (v * 10) + (int)(str[vi] - '0');
                }
                if ((v != 0 || !negative) && v < (1L << 53) - 1)
                {
                    if (negative)
                    {
                        v = -v;
                    }
                    if (kind == JSONOptions.ConversionMode.Double)
                    {
                        return(CBORObject.FromObject((double)v));
                    }
                    else if (kind == JSONOptions.ConversionMode.Decimal128)
                    {
                        return(CBORObject.FromObject(EDecimal.FromInt64(v)));
                    }
                    else
                    {
                        return(CBORObject.FromObject(v));
                    }
                }
            }
            if (kind == JSONOptions.ConversionMode.Full)
            {
                if (!haveDecimalPoint && !haveExponent)
                {
                    EInteger ei = EInteger.FromSubstring(str, initialOffset, endPos);
                    if (preserveNegativeZero && ei.IsZero && negative)
                    {
                        // TODO: In next major version, change to EDecimal.NegativeZero
                        return(CBORObject.FromFloatingPointBits(0x8000, 2));
                    }
                    return(CBORObject.FromObject(ei));
                }
                if (!haveExponent && haveDecimalPoint && (endPos - numOffset) <= 19)
                {
                    // No more than 18 digits plus one decimal point (which
                    // should fit a long)
                    long lv   = 0L;
                    int  expo = -(endPos - (decimalPointPos + 1));
                    int  vi   = numOffset;
                    for (; vi < decimalPointPos; ++vi)
                    {
                        lv = checked ((lv * 10) + (int)(str[vi] - '0'));
                    }
                    for (vi = decimalPointPos + 1; vi < endPos; ++vi)
                    {
                        lv = checked ((lv * 10) + (int)(str[vi] - '0'));
                    }
                    if (negative)
                    {
                        lv = -lv;
                    }
                    if (!negative || lv != 0)
                    {
                        CBORObject cbor = CBORObject.NewArray()
                                          .Add(expo).Add(lv);
                        return(CBORObject.FromObjectAndTag(cbor, 4));
                    }
                }
                EDecimal ed = EDecimal.FromString(
                    str,
                    initialOffset,
                    endPos - initialOffset);
                if (ed.IsZero && negative)
                {
                    if (preserveNegativeZero && ed.Exponent.IsZero)
                    {
                        // TODO: In next major version, use EDecimal
                        return(CBORObject.FromFloatingPointBits(0x8000, 2));
                    }
                    else if (!preserveNegativeZero)
                    {
                        ed = ed.Negate();
                    }
                }
                return(CBORObject.FromObject(ed));
            }
            else if (kind == JSONOptions.ConversionMode.Double)
            {
                double dbl = EFloat.FromString(
                    str,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Binary64).ToDouble();
                if (!preserveNegativeZero && dbl == 0.0)
                {
                    dbl = 0.0;
                }
                return(CBORObject.FromObject(dbl));
            }
            else if (kind == JSONOptions.ConversionMode.Decimal128)
            {
                EDecimal ed = EDecimal.FromString(
                    str,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Decimal128);
                if (!preserveNegativeZero && ed.IsNegative && ed.IsZero)
                {
                    ed = ed.Negate();
                }
                return(CBORObject.FromObject(ed));
            }
            else if (kind == JSONOptions.ConversionMode.IntOrFloatFromDouble)
            {
                double dbl = EFloat.FromString(
                    str,
                    initialOffset,
                    endPos - initialOffset,
                    EContext.Binary64).ToDouble();
                if (!Double.IsNaN(dbl) && dbl >= -9007199254740991.0 &&
                    dbl <= 9007199254740991.0 && Math.Floor(dbl) == dbl)
                {
                    var idbl = (long)dbl;
                    return(CBORObject.FromObject(idbl));
                }
                return(CBORObject.FromObject(dbl));
            }
            else if (kind == JSONOptions.ConversionMode.IntOrFloat)
            {
                EContext ctx = EContext.Binary64.WithBlankFlags();
                double   dbl = EFloat.FromString(
                    str,
                    initialOffset,
                    endPos - initialOffset,
                    ctx).ToDouble();
                if ((ctx.Flags & EContext.FlagInexact) != 0)
                {
                    // Inexact conversion to double, meaning that the string doesn't
                    // represent an integer in [-(2^53)+1, 2^53), which is representable
                    // exactly as double, so treat as ConversionMode.Double
                    if (!preserveNegativeZero && dbl == 0.0)
                    {
                        dbl = 0.0;
                    }
                    return(CBORObject.FromObject(dbl));
                }
                else
                {
                    // Exact conversion; treat as ConversionMode.IntToFloatFromDouble
                    if (!Double.IsNaN(dbl) && dbl >= -9007199254740991.0 &&
                        dbl <= 9007199254740991.0 && Math.Floor(dbl) == dbl)
                    {
                        var idbl = (long)dbl;
                        return(CBORObject.FromObject(idbl));
                    }
                    return(CBORObject.FromObject(dbl));
                }
            }
            else
            {
                throw new ArgumentException("Unsupported conversion kind.");
            }
        }
Esempio n. 13
0
        /// <include file='../../docs.xml'
        /// path='docs/doc[@name="M:PeterO.Cbor.CBORDataUtilities.ParseJSONNumber(System.String,System.Boolean,System.Boolean,System.Boolean)"]/*'/>
        public static CBORObject ParseJSONNumber(
            string str,
            bool integersOnly,
            bool positiveOnly,
            bool preserveNegativeZero)
        {
            if (String.IsNullOrEmpty(str))
            {
                return(null);
            }
            var offset   = 0;
            var negative = false;

            if (str[0] == '-' && !positiveOnly)
            {
                negative = true;
                ++offset;
            }
            var          mantInt                = 0;
            FastInteger2 mant                   = null;
            var          mantBuffer             = 0;
            var          mantBufferMult         = 1;
            var          expBuffer              = 0;
            var          expBufferMult          = 1;
            var          haveDecimalPoint       = false;
            var          haveDigits             = false;
            var          haveDigitsAfterDecimal = false;
            var          haveExponent           = false;
            var          newScaleInt            = 0;
            FastInteger2 newScale               = null;
            int          i = offset;

            // Ordinary number
            if (i < str.Length && str[i] == '0')
            {
                ++i;
                haveDigits = true;
                if (i == str.Length)
                {
                    if (preserveNegativeZero && negative)
                    {
                        return(CBORObject.FromObject(
                                   EDecimal.NegativeZero));
                    }
                    return(CBORObject.FromObject(0));
                }
                if (!integersOnly)
                {
                    if (str[i] == '.')
                    {
                        haveDecimalPoint = true;
                        ++i;
                    }
                    else if (str[i] == 'E' || str[i] == 'e')
                    {
                        haveExponent = true;
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    return(null);
                }
            }
            for (; i < str.Length; ++i)
            {
                if (str[i] >= '0' && str[i] <= '9')
                {
                    var thisdigit = (int)(str[i] - '0');
                    if (mantInt > MaxSafeInt)
                    {
                        if (mant == null)
                        {
                            mant           = new FastInteger2(mantInt);
                            mantBuffer     = thisdigit;
                            mantBufferMult = 10;
                        }
                        else
                        {
                            if (mantBufferMult >= 1000000000)
                            {
                                mant.Multiply(mantBufferMult).AddInt(mantBuffer);
                                mantBuffer     = thisdigit;
                                mantBufferMult = 10;
                            }
                            else
                            {
                                mantBufferMult *= 10;
                                mantBuffer      = (mantBuffer << 3) + (mantBuffer << 1);
                                mantBuffer     += thisdigit;
                            }
                        }
                    }
                    else
                    {
                        mantInt *= 10;
                        mantInt += thisdigit;
                    }
                    haveDigits = true;
                    if (haveDecimalPoint)
                    {
                        haveDigitsAfterDecimal = true;
                        if (newScaleInt == Int32.MinValue)
                        {
                            newScale = newScale ?? (new FastInteger2(newScaleInt));
                            newScale.AddInt(-1);
                        }
                        else
                        {
                            --newScaleInt;
                        }
                    }
                }
                else if (!integersOnly && str[i] == '.')
                {
                    if (!haveDigits)
                    {
                        // no digits before the decimal point
                        return(null);
                    }
                    if (haveDecimalPoint)
                    {
                        return(null);
                    }
                    haveDecimalPoint = true;
                }
                else if (!integersOnly && (str[i] == 'E' || str[i] == 'e'))
                {
                    haveExponent = true;
                    ++i;
                    break;
                }
                else
                {
                    return(null);
                }
            }
            if (!haveDigits || (haveDecimalPoint && !haveDigitsAfterDecimal))
            {
                return(null);
            }
            if (mant != null && (mantBufferMult != 1 || mantBuffer != 0))
            {
                mant.Multiply(mantBufferMult).AddInt(mantBuffer);
            }
            if (haveExponent)
            {
                FastInteger2 exp    = null;
                var          expInt = 0;
                offset     = 1;
                haveDigits = false;
                if (i == str.Length)
                {
                    return(null);
                }
                if (str[i] == '+' || str[i] == '-')
                {
                    if (str[i] == '-')
                    {
                        offset = -1;
                    }
                    ++i;
                }
                for (; i < str.Length; ++i)
                {
                    if (str[i] >= '0' && str[i] <= '9')
                    {
                        haveDigits = true;
                        var thisdigit = (int)(str[i] - '0');
                        if (expInt > MaxSafeInt)
                        {
                            if (exp == null)
                            {
                                exp           = new FastInteger2(expInt);
                                expBuffer     = thisdigit;
                                expBufferMult = 10;
                            }
                            else
                            {
                                if (expBufferMult >= 1000000000)
                                {
                                    exp.Multiply(expBufferMult).AddInt(expBuffer);
                                    expBuffer     = thisdigit;
                                    expBufferMult = 10;
                                }
                                else
                                {
                                    // multiply expBufferMult and expBuffer each by 10
                                    expBufferMult = (expBufferMult << 3) + (expBufferMult << 1);
                                    expBuffer     = (expBuffer << 3) + (expBuffer << 1);
                                    expBuffer    += thisdigit;
                                }
                            }
                        }
                        else
                        {
                            expInt *= 10;
                            expInt += thisdigit;
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }
                if (!haveDigits)
                {
                    return(null);
                }
                if (exp != null && (expBufferMult != 1 || expBuffer != 0))
                {
                    exp.Multiply(expBufferMult).AddInt(expBuffer);
                }
                if (offset >= 0 && newScaleInt == 0 && newScale == null && exp == null)
                {
                    newScaleInt = expInt;
                }
                else if (exp == null)
                {
                    newScale = newScale ?? (new FastInteger2(newScaleInt));
                    if (offset < 0)
                    {
                        newScale.SubtractInt(expInt);
                    }
                    else if (expInt != 0)
                    {
                        newScale.AddInt(expInt);
                    }
                }
                else
                {
                    newScale = newScale ?? (new FastInteger2(newScaleInt));
                    if (offset < 0)
                    {
                        newScale.Subtract(exp);
                    }
                    else
                    {
                        newScale.Add(exp);
                    }
                }
            }
            if (i != str.Length)
            {
                // End of the string wasn't reached, so isn't a number
                return(null);
            }
            if ((newScale == null && newScaleInt == 0) || (newScale != null &&
                                                           newScale.Sign == 0))
            {
                // No fractional part
                if (mant != null && mant.CanFitInInt32())
                {
                    mantInt = mant.AsInt32();
                    mant    = null;
                }
                if (mant == null)
                {
                    // NOTE: mantInt can only be 0 or greater, so overflow is impossible
#if DEBUG
                    if (mantInt < 0)
                    {
                        throw new ArgumentException("mantInt (" + mantInt +
                                                    ") is less than 0");
                    }
#endif

                    if (negative)
                    {
                        mantInt = -mantInt;
                        if (preserveNegativeZero && mantInt == 0)
                        {
                            return(CBORObject.FromObject(
                                       EDecimal.NegativeZero));
                        }
                    }
                    return(CBORObject.FromObject(mantInt));
                }
                else
                {
                    EInteger bigmant2 = mant.AsBigInteger();
                    if (negative)
                    {
                        bigmant2 = -(EInteger)bigmant2;
                    }
                    return(CBORObject.FromObject(bigmant2));
                }
            }
            else
            {
                EInteger bigmant = (mant == null) ? ((EInteger)mantInt) :
                                   mant.AsBigInteger();
                EInteger bigexp = (newScale == null) ? ((EInteger)newScaleInt) :
                                  newScale.AsBigInteger();
                if (negative)
                {
                    bigmant = -(EInteger)bigmant;
                }
                EDecimal edec;
                edec = EDecimal.Create(
                    bigmant,
                    bigexp);
                if (negative && preserveNegativeZero && bigmant.IsZero)
                {
                    EDecimal negzero = EDecimal.NegativeZero;
                    negzero = negzero.Quantize(bigexp, null);
                    edec    = negzero.Subtract(edec);
                }
                return(CBORObject.FromObject(edec));
            }
        }
Esempio n. 14
0
        public CBORObject ReadForFirstByte(int firstbyte)
        {
            if (this.depth > 500)
            {
                throw new CBORException("Too deeply nested");
            }
            if (firstbyte < 0)
            {
                throw new CBORException("Premature end of data");
            }
            if (firstbyte == 0xff)
            {
                throw new CBORException("Unexpected break code encountered");
            }
            int        type       = (firstbyte >> 5) & 0x07;
            int        additional = firstbyte & 0x1f;
            long       uadditional;
            CBORObject fixedObject;

            if (this.options.Ctap2Canonical)
            {
                if (additional >= 0x1c)
                {
                    // NOTE: Includes stop byte and indefinite length data items
                    throw new CBORException("Invalid canonical CBOR encountered");
                }
                // Check if this represents a fixed object (NOTE: All fixed objects
                // comply with CTAP2 canonical CBOR).
                fixedObject = CBORObject.GetFixedObject(firstbyte);
                if (fixedObject != null)
                {
                    return(fixedObject);
                }
                if (type == 6)
                {
                    throw new CBORException("Tags not allowed in canonical CBOR");
                }
                uadditional = ReadDataLength(
                    this.stream,
                    firstbyte,
                    type,
                    type == 7);
                if (type == 0)
                {
                    return((uadditional >> 63) != 0 ?
                           CBORObject.FromObject(ToUnsignedEInteger(uadditional)) :
                           CBORObject.FromObject(uadditional));
                }
                else if (type == 1)
                {
                    return((uadditional >> 63) != 0 ? CBORObject.FromObject(
                               ToUnsignedEInteger(uadditional).Add(1).Negate()) :
                           CBORObject.FromObject((-uadditional) - 1L));
                }
                else if (type == 7)
                {
                    if (additional < 24)
                    {
                        return(CBORObject.FromSimpleValue(additional));
                    }
                    else if (additional == 24 && uadditional < 32)
                    {
                        throw new CBORException("Invalid simple value encoding");
                    }
                    else if (additional == 24)
                    {
                        return(CBORObject.FromSimpleValue((int)uadditional));
                    }
                    else if (additional == 25)
                    {
                        return(CBORObject.FromFloatingPointBits(uadditional, 2));
                    }
                    else if (additional == 26)
                    {
                        return(CBORObject.FromFloatingPointBits(uadditional, 4));
                    }
                    else if (additional == 27)
                    {
                        return(CBORObject.FromFloatingPointBits(uadditional, 8));
                    }
                }
                else if (type >= 2 && type <= 5)
                {
                    return(this.ReadStringArrayMap(type, uadditional));
                }
                throw new CBORException("Unexpected data encountered");
            }
            int expectedLength = CBORObject.GetExpectedLength(firstbyte);

            // Data checks
            if (expectedLength == -1)
            {
                // if the head byte is invalid
                throw new CBORException("Unexpected data encountered");
            }
            // Check if this represents a fixed object
            fixedObject = CBORObject.GetFixedObject(firstbyte);
            if (fixedObject != null)
            {
                return(fixedObject);
            }
            // Read fixed-length data
            byte[] data = null;
            if (expectedLength != 0)
            {
                data = new byte[expectedLength];
                // include the first byte because GetFixedLengthObject
                // will assume it exists for some head bytes
                data[0] = unchecked ((byte)firstbyte);
                if (expectedLength > 1 &&
                    this.stream.Read(data, 1, expectedLength - 1) != expectedLength
                    - 1)
                {
                    throw new CBORException("Premature end of data");
                }
                CBORObject cbor = CBORObject.GetFixedLengthObject(firstbyte, data);
                if (this.stringRefs != null && (type == 2 || type == 3))
                {
                    this.stringRefs.AddStringIfNeeded(cbor, expectedLength - 1);
                }
                return(cbor);
            }
            if (additional == 31)
            {
                // Indefinite-length for major types 2 to 5 (other major
                // types were already handled in the call to
                // GetFixedLengthObject).
                switch (type)
                {
                case 2: {
                    // Streaming byte string
                    using (var ms = new MemoryStream()) {
                        // Requires same type as this one
                        while (true)
                        {
                            int nextByte = this.stream.ReadByte();
                            if (nextByte == 0xff)
                            {
                                // break if the "break" code was read
                                break;
                            }
                            long len = ReadDataLength(this.stream, nextByte, 2);
                            if ((len >> 63) != 0 || len > Int32.MaxValue)
                            {
                                throw new CBORException("Length" + ToUnsignedEInteger(len)
                                                        +
                                                        " is bigger than supported ");
                            }
                            if (nextByte != 0x40)
                            {
                                // NOTE: 0x40 means the empty byte string
                                ReadByteData(this.stream, len, ms);
                            }
                        }
                        if (ms.Position > Int32.MaxValue)
                        {
                            throw new
                                  CBORException("Length of bytes to be streamed is bigger" +
                                                "\u0020than supported ");
                        }
                        data = ms.ToArray();
                        return(CBORObject.FromRaw(data));
                    }
                }

                case 3: {
                    // Streaming text string
                    var builder = new StringBuilder();
                    while (true)
                    {
                        int nextByte = this.stream.ReadByte();
                        if (nextByte == 0xff)
                        {
                            // break if the "break" code was read
                            break;
                        }
                        long len = ReadDataLength(this.stream, nextByte, 3);
                        if ((len >> 63) != 0 || len > Int32.MaxValue)
                        {
                            throw new CBORException("Length" + ToUnsignedEInteger(len) +
                                                    " is bigger than supported");
                        }
                        if (nextByte != 0x60)
                        {
                            // NOTE: 0x60 means the empty string
                            if (PropertyMap.ExceedsKnownLength(this.stream, len))
                            {
                                throw new CBORException("Premature end of data");
                            }
                            switch (
                                DataUtilities.ReadUtf8(
                                    this.stream,
                                    (int)len,
                                    builder,
                                    false))
                            {
                            case -1:
                                throw new CBORException("Invalid UTF-8");

                            case -2:
                                throw new CBORException("Premature end of data");
                            }
                        }
                    }
                    return(CBORObject.FromRaw(builder.ToString()));
                }

                case 4: {
                    CBORObject cbor    = CBORObject.NewArray();
                    var        vtindex = 0;
                    // Indefinite-length array
                    while (true)
                    {
                        int headByte = this.stream.ReadByte();
                        if (headByte < 0)
                        {
                            throw new CBORException("Premature end of data");
                        }
                        if (headByte == 0xff)
                        {
                            // Break code was read
                            break;
                        }
                        ++this.depth;
                        CBORObject o = this.ReadForFirstByte(
                            headByte);
                        --this.depth;
                        cbor.Add(o);
                        ++vtindex;
                    }
                    return(cbor);
                }

                case 5: {
                    CBORObject cbor = CBORObject.NewMap();
                    // Indefinite-length map
                    while (true)
                    {
                        int headByte = this.stream.ReadByte();
                        if (headByte < 0)
                        {
                            throw new CBORException("Premature end of data");
                        }
                        if (headByte == 0xff)
                        {
                            // Break code was read
                            break;
                        }
                        ++this.depth;
                        CBORObject key   = this.ReadForFirstByte(headByte);
                        CBORObject value = this.ReadInternal();
                        --this.depth;
                        if (!this.options.AllowDuplicateKeys)
                        {
                            if (cbor.ContainsKey(key))
                            {
                                throw new CBORException("Duplicate key already exists");
                            }
                        }
                        cbor[key] = value;
                    }
                    return(cbor);
                }

                default: throw new CBORException("Unexpected data encountered");
                }
            }
            EInteger bigintAdditional = EInteger.Zero;

            uadditional = ReadDataLength(this.stream, firstbyte, type);
            // The following doesn't check for major types 0 and 1,
            // since all of them are fixed-length types and are
            // handled in the call to GetFixedLengthObject.
            if (type >= 2 && type <= 5)
            {
                return(this.ReadStringArrayMap(type, uadditional));
            }
            if (type == 6) // Tagged item
            {
                var haveFirstByte = false;
                var newFirstByte  = -1;
                if (this.options.ResolveReferences && (uadditional >> 32) == 0)
                {
                    // NOTE: HandleItemTag treats only certain tags up to 256 specially
                    this.HandleItemTag(uadditional);
                }
                ++this.depth;
                CBORObject o = haveFirstByte ? this.ReadForFirstByte(
                    newFirstByte) : this.ReadInternal();
                --this.depth;
                if ((uadditional >> 63) != 0)
                {
                    return(CBORObject.FromObjectAndTag(o,
                                                       ToUnsignedEInteger(uadditional)));
                }
                if (uadditional < 65536)
                {
                    if (this.options.ResolveReferences)
                    {
                        int uaddl = uadditional >= 257 ? 257 : (uadditional < 0 ? 0 :
                                                                (int)uadditional);
                        switch (uaddl)
                        {
                        case 256:
                            // string tag
                            this.stringRefs.Pop();
                            break;

                        case 25:
                            // stringref tag
                            if (o.IsTagged || o.Type != CBORType.Integer)
                            {
                                throw new CBORException("stringref must be an unsigned" +
                                                        "\u0020integer");
                            }
                            return(this.stringRefs.GetString(o.AsEIntegerValue()));
                        }
                    }
                    return(CBORObject.FromObjectAndTag(
                               o,
                               (int)uadditional));
                }
                return(CBORObject.FromObjectAndTag(
                           o,
                           (EInteger)uadditional));
            }
            throw new CBORException("Unexpected data encountered");
        }
Esempio n. 15
0
        public static CBORObject Subtract(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }
            if (b == null)
            {
                throw new ArgumentNullException("b");
            }
            if (a.Type != CBORType.Number)
            {
                throw new ArgumentException("a.Type (" + a.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            if (b.Type != CBORType.Number)
            {
                throw new ArgumentException("b.Type (" + b.Type +
                                            ") is not equal to " + CBORType.Number);
            }
            object objA  = a.ThisItem;
            object objB  = b.ThisItem;
            int    typeA = a.ItemType;
            int    typeB = b.ItemType;

            if (typeA == CBORObject.CBORObjectTypeInteger && typeB ==
                CBORObject.CBORObjectTypeInteger)
            {
                var valueA = (long)objA;
                var valueB = (long)objB;
                if ((valueB < 0 && Int64.MaxValue + valueB < valueA) ||
                    (valueB > 0 && Int64.MinValue + valueB > valueA))
                {
                    // would overflow, convert to EInteger
                    return(CBORObject.FromObject(((EInteger)valueA) -
                                                 (EInteger)valueB));
                }
                return(CBORObject.FromObject(valueA - valueB));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedRational ||
                typeB == CBORObject.CBORObjectTypeExtendedRational)
            {
                ERational e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA);
                ERational e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB);
                return(CBORObject.FromObject(e1.Subtract(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedDecimal ||
                typeB == CBORObject.CBORObjectTypeExtendedDecimal)
            {
                EDecimal e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA);
                EDecimal e2 =
                    CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB);
                return(CBORObject.FromObject(e1.Subtract(e2)));
            }
            if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB ==
                CBORObject.CBORObjectTypeExtendedFloat ||
                typeA == CBORObject.CBORObjectTypeDouble || typeB ==
                CBORObject.CBORObjectTypeDouble ||
                typeA == CBORObject.CBORObjectTypeSingle || typeB ==
                CBORObject.CBORObjectTypeSingle)
            {
                EFloat e1 =
                    CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA);
                EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB);
                return(CBORObject.FromObject(e1.Subtract(e2)));
            }
            else
            {
                EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA);
                EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB);
                return(CBORObject.FromObject(b1 - (EInteger)b2));
            }
        }
Esempio n. 16
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);
        }
Esempio n. 17
0
 public static CBORObject FromObject(ulong value)
 {
     return(CBORObject.FromObject(UInt64ToEInteger(value)));
 }
Esempio n. 18
0
        /// <summary>Converts a date/time in the form of a year, month, day,
        /// hour, minute, second, fractional seconds, and time offset to a CBOR
        /// object.</summary>
        /// <param name='bigYear'>The parameter <paramref name='bigYear'/> is a
        /// Numbers.EInteger object.</param>
        /// <param name='lesserFields'>An array that will store the fields
        /// (other than the year) of the date and time. See the
        /// TryGetDateTimeFields method for information on the "lesserFields"
        /// parameter.</param>
        /// <returns>A CBOR object encoding the given date fields according to
        /// the conversion type used to create this date converter.</returns>
        /// <exception cref='ArgumentNullException'>The parameter <paramref
        /// name='bigYear'/> or <paramref name='lesserFields'/> is
        /// null.</exception>
        /// <exception cref='PeterO.Cbor.CBORException'>An error occurred in
        /// conversion.</exception>
        public CBORObject DateTimeFieldsToCBORObject(EInteger bigYear, int[]
                                                     lesserFields)
        {
            if (bigYear == null)
            {
                throw new ArgumentNullException(nameof(bigYear));
            }
            if (lesserFields == null)
            {
                throw new ArgumentNullException(nameof(lesserFields));
            }
            if (lesserFields.Length < 7)
            {
                throw new ArgumentException("\"lesserFields\" + \"'s length\" (" +
                                            lesserFields.Length + ") is not greater or equal to 7");
            }
            try {
                switch (this.convType)
                {
                case ConversionType.TaggedString: {
                    string str = CBORUtilities.ToAtomDateTimeString(bigYear,
                                                                    lesserFields);
                    return(CBORObject.FromObjectAndTag(str, 0));
                }

                case ConversionType.TaggedNumber:
                case ConversionType.UntaggedNumber:
                    try {
                        var    status = new int[1];
                        EFloat ef     = CBORUtilities.DateTimeToIntegerOrDouble(
                            bigYear,
                            lesserFields,
                            status);
                        if (status[0] == 0)
                        {
                            return(this.convType == ConversionType.TaggedNumber ?
                                   CBORObject.FromObjectAndTag(ef.ToEInteger(), 1) :
                                   CBORObject.FromObject(ef.ToEInteger()));
                        }
                        else if (status[0] == 1)
                        {
                            return(this.convType == ConversionType.TaggedNumber ?
                                   CBORObject.FromFloatingPointBits(ef.ToDoubleBits(),
                                                                    8).WithTag(1) : CBORObject.FromFloatingPointBits(ef.ToDoubleBits(), 8));
                        }
                        else
                        {
                            throw new CBORException("Too big or small to fit an integer" +
                                                    "\u0020or" +
                                                    "\u0020floating-point number");
                        }
                    } catch (ArgumentException ex) {
                        throw new CBORException(ex.Message, ex);
                    }

                default:
                    throw new CBORException("Internal error");
                }
            } catch (ArgumentException ex) {
                throw new CBORException(ex.Message, ex);
            }
        }
Esempio n. 19
0
        public static byte[] CtapCanonicalEncode(CBORObject a)
        {
            CBORObject cbor       = a.Untag();
            CBORType   valueAType = cbor.Type;

            try {
                if (valueAType == CBORType.Array)
                {
                    using (var ms = new MemoryStream()) {
                        CBORObject.WriteValue(ms, 4, cbor.Count);
                        for (var i = 0; i < cbor.Count; ++i)
                        {
                            byte[] bytes = CtapCanonicalEncode(cbor[i]);
                            ms.Write(bytes, 0, bytes.Length);
                        }
                        return(ms.ToArray());
                    }
                }
                else if (valueAType == CBORType.Map)
                {
                    var sortedKeys = new List <CBORObject>();
                    foreach (CBORObject key in cbor.Keys)
                    {
                        sortedKeys.Add(key);
                    }
                    sortedKeys.Sort(new CtapComparer());
                    using (var ms = new MemoryStream()) {
                        CBORObject.WriteValue(ms, 5, cbor.Count);
                        foreach (CBORObject key in sortedKeys)
                        {
                            byte[] bytes = CtapCanonicalEncode(key);
                            ms.Write(bytes, 0, bytes.Length);
                            bytes = CtapCanonicalEncode(cbor[key]);
                            ms.Write(bytes, 0, bytes.Length);
                        }
                        return(ms.ToArray());
                    }
                }
            } catch (IOException ex) {
                throw new InvalidOperationException(ex.ToString(), ex);
            }
            if (valueAType == CBORType.SimpleValue ||
                valueAType == CBORType.Boolean || valueAType == CBORType.ByteString ||
                valueAType == CBORType.TextString)
            {
                return(cbor.EncodeToBytes(CBOREncodeOptions.Default));
            }
            else if (valueAType == CBORType.Number)
            {
                if (cbor.CanFitInInt64())
                {
                    return(cbor.EncodeToBytes(CBOREncodeOptions.Default));
                }
                else
                {
                    cbor = CBORObject.FromObject(cbor.AsDouble());
                    return(cbor.EncodeToBytes(CBOREncodeOptions.Default));
                }
            }
            else
            {
                throw new ArgumentException("Invalid CBOR type.");
            }
        }