Example #1
0
 public CBORObject ValidateObject(CBORObject obj)
 {
     if (obj.Type == CBORType.TextString) {
     throw new CBORException("Not a text string");
       }
       return obj;
 }
Example #2
0
 public CBORObject ValidateObject(CBORObject obj)
 {
     if (obj.Type != CBORType.Array || obj.Count < 1) {
     throw new CBORException("Not an array, or is an empty array.");
       }
       return obj;
 }
Example #3
0
 public CBORObject ValidateObject(CBORObject obj)
 {
     if (!obj.IsFinite) {
     throw new CBORException("Not a valid date");
       }
       return obj;
 }
Example #4
0
 public CBORObject ValidateObject(CBORObject obj)
 {
     #if DEBUG
       if (obj == null) {
     throw new ArgumentNullException("obj");
       }
       #endif
       return obj;
 }
Example #5
0
        private void Parse(byte[] bytes)
        {
            var cborObject = CBORObject.DecodeFromBytes(bytes);
            var list = cborObject.ConvertToList();

            if (list.Count == 3)
            {
                header = list.ElementAt(0);
                payload = list.ElementAt(1);
                signature = list.ElementAt(2);
            }
        }
Example #6
0
 public CBORObject ValidateObject(CBORObject obj)
 {
     #if DEBUG
       if (obj == null) {
     throw new ArgumentNullException("obj");
       }
       #endif
       if (!obj.IsIntegral || !obj.CanFitInInt64() || obj.Sign < 0) {
     throw new CBORException("Not a 64-bit unsigned integer");
       }
       return obj;
 }
Example #7
0
        private Org.BouncyCastle.Math.BigInteger ConvertBigNum(PeterO.Cbor.CBORObject cbor)
        {
            byte[] rgb  = cbor.GetByteString();
            byte[] rgb2 = new byte[rgb.Length + 2];
            rgb2[0] = 0;
            rgb2[1] = 0;
            for (int i = 0; i < rgb.Length; i++)
            {
                rgb2[i + 2] = rgb[i];
            }

            return(new Org.BouncyCastle.Math.BigInteger(rgb2));
        }
Example #8
0
 public CBORObject ValidateObject(CBORObject obj)
 {
     #if DEBUG
       if (obj == null) {
     throw new ArgumentNullException("obj");
       }
       #endif
       // Return this object without tag 28
       #if DEBUG
       if (!obj.HasTag(28)) {
     throw new ArgumentException("doesn't satisfy obj.HasTag(28)");
       }
       #endif
       return obj.UntagOne();
 }
Example #9
0
        public static CBORObject Remainder(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException(nameof(a));
            }
            if (b == null)
            {
                throw new ArgumentNullException(nameof(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));
            }
        }
Example #10
0
        internal static void WriteJSONToInternal(
            CBORObject obj,
            StringOutput writer,
            JSONOptions options,
            IList <CBORObject> stack)
        {
            if (obj.IsNumber)
            {
                writer.WriteString(CBORNumber.FromCBORObject(obj).ToJSONString());
                return;
            }
            switch (obj.Type)
            {
            case CBORType.Integer:
            case CBORType.FloatingPoint: {
                CBORObject untaggedObj = obj.Untag();
                writer.WriteString(
                    CBORNumber.FromCBORObject(untaggedObj).ToJSONString());
                break;
            }

            case CBORType.Boolean: {
                if (obj.IsTrue)
                {
                    writer.WriteString("true");
                    return;
                }
                if (obj.IsFalse)
                {
                    writer.WriteString("false");
                    return;
                }
                return;
            }

            case CBORType.SimpleValue: {
                writer.WriteString("null");
                return;
            }

            case CBORType.ByteString: {
                byte[] byteArray = obj.GetByteString();
                if (byteArray.Length == 0)
                {
                    writer.WriteString("\"\"");
                    return;
                }
                writer.WriteCodePoint((int)'\"');
                if (obj.HasTag(22))
                {
                    // Base64 with padding
                    Base64.WriteBase64(
                        writer,
                        byteArray,
                        0,
                        byteArray.Length,
                        true);
                }
                else if (obj.HasTag(23))
                {
                    // Write as base16
                    for (int i = 0; i < byteArray.Length; ++i)
                    {
                        writer.WriteCodePoint((int)Hex16[(byteArray[i] >> 4) & 15]);
                        writer.WriteCodePoint((int)Hex16[byteArray[i] & 15]);
                    }
                }
                else
                {
                    // Base64url no padding
                    Base64.WriteBase64URL(
                        writer,
                        byteArray,
                        0,
                        byteArray.Length,
                        false);
                }
                writer.WriteCodePoint((int)'\"');
                break;
            }

            case CBORType.TextString: {
                string thisString = obj.AsString();
                if (thisString.Length == 0)
                {
                    writer.WriteString("\"\"");
                    return;
                }
                writer.WriteCodePoint((int)'\"');
                WriteJSONStringUnquoted(thisString, writer, options);
                writer.WriteCodePoint((int)'\"');
                break;
            }

            case CBORType.Array: {
                writer.WriteCodePoint((int)'[');
                for (var i = 0; i < obj.Count; ++i)
                {
                    if (i > 0)
                    {
                        writer.WriteCodePoint((int)',');
                    }
                    bool pop = CheckCircularRef(stack, obj, obj[i]);
                    WriteJSONToInternal(obj[i], writer, options, stack);
                    PopRefIfNeeded(stack, pop);
                }
                writer.WriteCodePoint((int)']');
                break;
            }

            case CBORType.Map: {
                var first            = true;
                var hasNonStringKeys = false;
                ICollection <KeyValuePair <CBORObject, CBORObject> > entries =
                    obj.Entries;
                foreach (KeyValuePair <CBORObject, CBORObject> entry in entries)
                {
                    CBORObject key = entry.Key;
                    if (key.Type != CBORType.TextString ||
                        key.IsTagged)
                    {
                        // treat a non-text-string item or a tagged item
                        // as having non-string keys
                        hasNonStringKeys = true;
                        break;
                    }
                }
                if (!hasNonStringKeys)
                {
                    writer.WriteCodePoint((int)'{');
                    foreach (KeyValuePair <CBORObject, CBORObject> entry in entries)
                    {
                        CBORObject key   = entry.Key;
                        CBORObject value = entry.Value;
                        if (!first)
                        {
                            writer.WriteCodePoint((int)',');
                        }
                        writer.WriteCodePoint((int)'\"');
                        WriteJSONStringUnquoted(key.AsString(), writer, options);
                        writer.WriteCodePoint((int)'\"');
                        writer.WriteCodePoint((int)':');
                        bool pop = CheckCircularRef(stack, obj, value);
                        WriteJSONToInternal(value, writer, options, stack);
                        PopRefIfNeeded(stack, pop);
                        first = false;
                    }
                    writer.WriteCodePoint((int)'}');
                }
                else
                {
                    // This map has non-string keys
                    IDictionary <string, CBORObject> stringMap = new
                                                                 Dictionary <string, CBORObject>();
                    // Copy to a map with String keys, since
                    // some keys could be duplicates
                    // when serialized to strings
                    foreach (KeyValuePair <CBORObject, CBORObject> entry
                             in entries)
                    {
                        CBORObject key   = entry.Key;
                        CBORObject value = entry.Value;
                        string     str   = null;
                        switch (key.Type)
                        {
                        case CBORType.TextString:
                            str = key.AsString();
                            break;

                        case CBORType.Array:
                        case CBORType.Map: {
                            var  sb  = new StringBuilder();
                            var  sw  = new StringOutput(sb);
                            bool pop = CheckCircularRef(stack, obj, key);
                            WriteJSONToInternal(key, sw, options, stack);
                            PopRefIfNeeded(stack, pop);
                            str = sb.ToString();
                            break;
                        }

                        default: str = key.ToJSONString(options);
                            break;
                        }
                        if (stringMap.ContainsKey(str))
                        {
                            throw new CBORException(
                                      "Duplicate JSON string equivalents of map" +
                                      "\u0020keys");
                        }
                        stringMap[str] = value;
                    }
                    first = true;
                    writer.WriteCodePoint((int)'{');
                    foreach (KeyValuePair <string, CBORObject> entry in stringMap)
                    {
                        string     key   = entry.Key;
                        CBORObject value = entry.Value;
                        if (!first)
                        {
                            writer.WriteCodePoint((int)',');
                        }
                        writer.WriteCodePoint((int)'\"');
                        WriteJSONStringUnquoted((string)key, writer, options);
                        writer.WriteCodePoint((int)'\"');
                        writer.WriteCodePoint((int)':');
                        bool pop = CheckCircularRef(stack, obj, value);
                        WriteJSONToInternal(value, writer, options, stack);
                        PopRefIfNeeded(stack, pop);
                        first = false;
                    }
                    writer.WriteCodePoint((int)'}');
                }
                break;
            }

            default:
                throw new InvalidOperationException("Unexpected item" +
                                                    "\u0020type");
            }
        }
Example #11
0
        internal static CBORObject ParseJSONNumber(
            char[] 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.");
            }
        }
        private CBORObject ParseJSONObject(int depth)
        {
            // Assumes that the last character read was '{'
            if (depth > 1000)
            {
                this.RaiseError("Too deeply nested");
            }
            int        c;
            CBORObject key = null;
            CBORObject obj;
            var        nextChar  = new int[1];
            var        seenComma = false;
            var        myHashMap = new Dictionary <CBORObject, CBORObject>();

            while (true)
            {
                c = this.SkipWhitespaceJSON();
                switch (c)
                {
                case -1:
                    this.RaiseError("A JSON object must end with '}'");
                    break;

                case '}':
                    if (seenComma)
                    {
                        // Situation like '{"0"=>1,}'
                        this.RaiseError("Trailing comma");
                        return(null);
                    }
                    return(CBORObject.FromRaw(myHashMap));

                default: {
                    // Read the next string
                    if (c < 0)
                    {
                        this.RaiseError("Unexpected end of data");
                        return(null);
                    }
                    if (c != '"')
                    {
                        this.RaiseError("Expected a string as a key");
                        return(null);
                    }
                    // Parse a string that represents the object's key.
                    // The tokenizer already checked the string for invalid
                    // surrogate pairs, so just call the CBORObject
                    // constructor directly
                    obj = CBORObject.FromRaw(this.NextJSONString());
                    key = obj;
                    if (!this.options.AllowDuplicateKeys &&
                        myHashMap.ContainsKey(obj))
                    {
                        this.RaiseError("Key already exists: " + key);
                        return(null);
                    }
                    break;
                }
                }
                if (this.SkipWhitespaceJSON() != ':')
                {
                    this.RaiseError("Expected a ':' after a key");
                }
                // NOTE: Will overwrite existing value
                myHashMap[key] = this.NextJSONValue(
                    this.SkipWhitespaceJSON(),
                    nextChar,
                    depth);
                switch (nextChar[0])
                {
                case ',':
                    seenComma = true;
                    break;

                case '}':
                    return(CBORObject.FromRaw(myHashMap));

                default: this.RaiseError("Expected a ',' or '}'");
                    break;
                }
            }
        }
Example #13
0
 public CBORObject ValidateObject(CBORObject obj)
 {
     return(ConvertToDecimalFrac(obj, false, this.extended));
 }
        private CBORObject ReadStringArrayMap(int type, long uadditional)
        {
            bool canonical = this.options.Ctap2Canonical;

            if (type == 2) // Byte string
            {
                if ((uadditional >> 31) != 0)
                {
                    throw new CBORException("Length of " +
                                            ToUnsignedEInteger(uadditional).ToString() + " is bigger" +
                                            "\u0020than supported");
                }
                int hint = (uadditional > Int32.MaxValue ||
                            (uadditional >> 63) != 0) ? Int32.MaxValue : (int)uadditional;
                byte[] data = ReadByteData(this.stream, uadditional, null);
                return(this.ObjectFromByteArray(data, hint));
            }
            if (type == 3) // Text string
            {
                if ((uadditional >> 31) != 0)
                {
                    throw new CBORException("Length of " +
                                            ToUnsignedEInteger(uadditional).ToString() + " is bigger" +
                                            "\u0020than supported");
                }
                if (PropertyMap.ExceedsKnownLength(this.stream, uadditional))
                {
                    throw new CBORException("Premature end of data");
                }
                var builder = new StringBuilder();
                switch (
                    DataUtilities.ReadUtf8(
                        this.stream,
                        (int)uadditional,
                        builder,
                        false))
                {
                case -1:
                    throw new CBORException("Invalid UTF-8");

                case -2:
                    throw new CBORException("Premature end of data");
                }
                CBORObject cbor = CBORObject.FromRaw(builder.ToString());
                if (this.stringRefs != null)
                {
                    int hint = (uadditional > Int32.MaxValue || (uadditional >> 63) !=
                                0) ? Int32.MaxValue : (int)uadditional;
                    this.stringRefs.AddStringIfNeeded(cbor, hint);
                }
                return(cbor);
            }
            if (type == 4) // Array
            {
                if (this.options.Ctap2Canonical && this.depth >= 4)
                {
                    throw new CBORException("Depth too high in canonical CBOR");
                }
                CBORObject cbor = CBORObject.NewArray();
                if ((uadditional >> 31) != 0)
                {
                    throw new CBORException("Length of " +
                                            ToUnsignedEInteger(uadditional).ToString() + " is bigger than" +
                                            "\u0020supported");
                }
                if (PropertyMap.ExceedsKnownLength(this.stream, uadditional))
                {
                    throw new CBORException("Remaining data too small for array" +
                                            "\u0020length");
                }
                ++this.depth;
                for (long i = 0; i < uadditional; ++i)
                {
                    cbor.Add(
                        this.ReadInternal());
                }
                --this.depth;
                return(cbor);
            }
            if (type == 5) // Map, type 5
            {
                if (this.options.Ctap2Canonical && this.depth >= 4)
                {
                    throw new CBORException("Depth too high in canonical CBOR");
                }
                CBORObject cbor = CBORObject.NewMap();
                if ((uadditional >> 31) != 0)
                {
                    throw new CBORException("Length of " +
                                            ToUnsignedEInteger(uadditional).ToString() + " is bigger than" +
                                            "\u0020supported");
                }
                if (PropertyMap.ExceedsKnownLength(this.stream, uadditional))
                {
                    throw new CBORException("Remaining data too small for map" +
                                            "\u0020length");
                }
                CBORObject             lastKey  = null;
                IComparer <CBORObject> comparer = CBORCanonical.Comparer;
                for (long i = 0; i < uadditional; ++i)
                {
                    ++this.depth;
                    CBORObject key   = this.ReadInternal();
                    CBORObject value = this.ReadInternal();
                    --this.depth;
                    if (this.options.Ctap2Canonical && lastKey != null)
                    {
                        int cmp = comparer.Compare(lastKey, key);
                        if (cmp > 0)
                        {
                            throw new CBORException("Map key not in canonical order");
                        }
                        else if (cmp == 0)
                        {
                            throw new CBORException("Duplicate map key");
                        }
                    }
                    if (!this.options.AllowDuplicateKeys)
                    {
                        if (cbor.ContainsKey(key))
                        {
                            throw new CBORException("Duplicate key already exists");
                        }
                    }
                    lastKey   = key;
                    cbor[key] = value;
                }
                return(cbor);
            }
            return(null);
        }
Example #15
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));
 }
Example #16
0
        public static CBORObject BuildCBORArray(int[] dimensions)
        {
            int zeroPos = dimensions.Length;

            for (var i = 0; i < dimensions.Length; ++i)
            {
                if (dimensions[i] == 0)
                {
                    {
                        zeroPos = i;
                    }
                    break;
                }
            }
            int arraydims = zeroPos - 1;

            if (arraydims <= 0)
            {
                return(CBORObject.NewArray());
            }
            var        stack    = new CBORObject[zeroPos];
            var        index    = new int[zeroPos];
            var        stackpos = 0;
            CBORObject ret      = CBORObject.NewArray();

            stack[0] = ret;
            index[0] = 0;
            for (var i = 0; i < dimensions[0]; ++i)
            {
                ret.Add(CBORObject.NewArray());
            }
            ++stackpos;
            while (stackpos > 0)
            {
                int curindex = index[stackpos - 1];
                if (curindex < stack[stackpos - 1].Count)
                {
                    CBORObject subobj = stack[stackpos - 1][curindex];
                    if (stackpos < zeroPos)
                    {
                        stack[stackpos] = subobj;
                        index[stackpos] = 0;
                        for (var i = 0; i < dimensions[stackpos]; ++i)
                        {
                            subobj.Add(CBORObject.NewArray());
                        }
                        ++index[stackpos - 1];
                        ++stackpos;
                    }
                    else
                    {
                        ++index[stackpos - 1];
                    }
                }
                else
                {
                    --stackpos;
                }
            }
            return(ret);
        }
Example #17
0
 public CBORObject ValidateObject(CBORObject obj)
 {
     return(CBORTag2.ConvertToBigNum(obj, true));
 }
Example #18
0
        private CBORObject NextJSONValue(
            int firstChar,
            int[] nextChar,
            int depth)
        {
            int        c   = firstChar;
            CBORObject obj = null;

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

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

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

            case 't': {
                // Parse true
                if (this.endPos - this.index <= 2 ||
                    (((int)this.bytes[this.index]) & 0xFF) != 'r' ||
                    (((int)this.bytes[this.index + 1]) & 0xFF) != 'u' ||
                    (((int)this.bytes[this.index + 2]) & 0xFF) != 'e')
                {
                    this.RaiseError("Value can't be parsed.");
                }
                this.index += 3;
                nextChar[0] = this.SkipWhitespaceJSON();
                return(CBORObject.True);
            }

            case 'f': {
                // Parse false
                if (this.endPos - this.index <= 3 ||
                    (((int)this.bytes[this.index]) & 0xFF) != 'a' ||
                    (((int)this.bytes[this.index + 1]) & 0xFF) != 'l' ||
                    (((int)this.bytes[this.index + 2]) & 0xFF) != 's' ||
                    (((int)this.bytes[this.index + 3]) & 0xFF) != 'e')
                {
                    this.RaiseError("Value can't be parsed.");
                }
                this.index += 4;
                nextChar[0] = this.SkipWhitespaceJSON();
                return(CBORObject.False);
            }

            case 'n': {
                // Parse null
                if (this.endPos - this.index <= 2 ||
                    (((int)this.bytes[this.index]) & 0xFF) != 'u' ||
                    (((int)this.bytes[this.index + 1]) & 0xFF) != 'l' ||
                    (((int)this.bytes[this.index + 2]) & 0xFF) != 'l')
                {
                    this.RaiseError("Value can't be parsed.");
                }
                this.index += 3;
                nextChar[0] = this.SkipWhitespaceJSON();
                return(CBORObject.Null);
            }

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

            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9': {
                // Parse a nonnegative number
                return(this.NextJSONNonnegativeNumber(c, nextChar));
            }

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

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

            if (obj.IsTagged)
            {
                if (sb == null)
                {
                    if (type == CBORType.TextString)
                    {
                        // The default capacity of StringBuilder may be too small
                        // for many strings, so set a suggested capacity
                        // explicitly
                        string str = obj.AsString();
                        sb = new StringBuilder(Math.Min(str.Length, 4096) + 16);
                    }
                    else
                    {
                        sb = new StringBuilder();
                    }
                }
                // Append opening tags if needed
                curobject = obj;
                while (curobject.IsTagged)
                {
                    EInteger ei = curobject.MostOuterTag;
                    sb.Append(ei.ToString());
                    sb.Append('(');
                    curobject = curobject.UntagOne();
                }
            }
            switch (type)
            {
            case CBORType.SimpleValue:
                sb = sb ?? new StringBuilder();
                if (obj.IsUndefined)
                {
                    sb.Append("undefined");
                }
                else if (obj.IsNull)
                {
                    sb.Append("null");
                }
                else
                {
                    sb.Append("simple(");
                    int  thisItemInt = obj.SimpleValue;
                    char c;
                    if (thisItemInt >= 100)
                    {
                        // NOTE: '0'-'9' have ASCII code 0x30-0x39
                        c = (char)(0x30 + ((thisItemInt / 100) % 10));
                        sb.Append(c);
                    }
                    if (thisItemInt >= 10)
                    {
                        c = (char)(0x30 + ((thisItemInt / 10) % 10));
                        sb.Append(c);
                        c = (char)(0x30 + (thisItemInt % 10));
                    }
                    else
                    {
                        c = (char)(0x30 + thisItemInt);
                    }
                    sb.Append(c);
                    sb.Append(')');
                }
                break;

            case CBORType.Boolean:
            case CBORType.Integer:
                simvalue = obj.Untag().ToJSONString();
                if (sb == null)
                {
                    return(simvalue);
                }
                sb.Append(simvalue);
                break;

            case CBORType.FloatingPoint: {
                long bits = obj.AsDoubleBits();
                simvalue = bits == DoubleNegInfinity ? "-Infinity" : (
                    bits == DoublePosInfinity ? "Infinity" : (
                        CBORUtilities.DoubleBitsNaN(bits) ? "NaN" :
                        obj.Untag().ToJSONString()));
                if (sb == null)
                {
                    return(simvalue);
                }
                sb.Append(simvalue);
                break;
            }

            case CBORType.ByteString: {
                sb = sb ?? new StringBuilder();
                sb.Append("h'");
                byte[] data   = obj.GetByteString();
                int    length = data.Length;
                for (var i = 0; i < length; ++i)
                {
                    sb.Append(HexAlphabet[(data[i] >> 4) & 15]);
                    sb.Append(HexAlphabet[data[i] & 15]);
                }
                sb.Append((char)0x27);
                break;
            }

            case CBORType.TextString: {
                sb = sb == null ? new StringBuilder() : sb;
                sb.Append('\"');
                string ostring = obj.AsString();
                sb.Append(ostring);
                sb.Append('\"');
                break;
            }

            case CBORType.Array: {
                sb = sb ?? new StringBuilder();
                var first = true;
                sb.Append('[');
                if (depth >= 50)
                {
                    sb.Append("...");
                }
                else
                {
                    for (var i = 0; i < obj.Count; ++i)
                    {
                        if (!first)
                        {
                            sb.Append(", ");
                        }
                        sb.Append(ToStringHelper(obj[i], depth + 1));
                        first = false;
                    }
                }
                sb.Append(']');
                break;
            }

            case CBORType.Map: {
                sb = sb ?? new StringBuilder();
                var first = true;
                sb.Append('{');
                if (depth >= 50)
                {
                    sb.Append("...");
                }
                else
                {
                    ICollection <KeyValuePair <CBORObject, CBORObject> > entries =
                        obj.Entries;
                    foreach (KeyValuePair <CBORObject, CBORObject> entry
                             in entries)
                    {
                        CBORObject key   = entry.Key;
                        CBORObject value = entry.Value;
                        if (!first)
                        {
                            sb.Append(", ");
                        }
                        sb.Append(ToStringHelper(key, depth + 1));
                        sb.Append(": ");
                        sb.Append(ToStringHelper(value, depth + 1));
                        first = false;
                    }
                }
                sb.Append('}');
                break;
            }

            default: {
                sb = sb ?? new StringBuilder();
                sb.Append("???");
                break;
            }
            }
            // Append closing tags if needed
            curobject = obj;
            while (curobject.IsTagged)
            {
                sb.Append(')');
                curobject = curobject.UntagOne();
            }
            return(sb.ToString());
        }
Example #21
0
        public static CBORObject Subtract(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException(nameof(a));
            }
            if (b == null)
            {
                throw new ArgumentNullException(nameof(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));
            }
        }
Example #22
0
        internal static ICBORNumber GetNumberInterface(CBORObject obj)
        {
            CBORNumber num = CBORNumber.FromCBORObject(obj);

            return((num == null) ? null : num.GetNumberInterface());
        }
Example #23
0
        private static CBORNumber BignumToNumber(CBORObject o)
        {
            if (o.Type != CBORType.ByteString)
            {
                return(null); // "Byte array expected");
            }
            bool negative = o.HasMostInnerTag(3);

            byte[] data = o.GetByteString();
            if (data.Length <= 7)
            {
                long x = 0;
                for (var i = 0; i < data.Length; ++i)
                {
                    x <<= 8;
                    x  |= ((long)data[i]) & 0xff;
                }
                if (negative)
                {
                    x = -x;
                    --x;
                }
                return(new CBORNumber(Kind.Integer, x));
            }
            int neededLength = data.Length;

            byte[]   bytes;
            EInteger bi;
            var      extended = false;

            if (((data[0] >> 7) & 1) != 0)
            {
                // Increase the needed length
                // if the highest bit is set, to
                // distinguish negative and positive
                // values
                ++neededLength;
                extended = true;
            }
            bytes = new byte[neededLength];
            for (var i = 0; i < data.Length; ++i)
            {
                bytes[i] = data[data.Length - 1 - i];
                if (negative)
                {
                    bytes[i] = (byte)((~((int)bytes[i])) & 0xff);
                }
            }
            if (extended)
            {
                bytes[bytes.Length - 1] = negative ? (byte)0xff : (byte)0;
            }
            bi = EInteger.FromBytes(bytes, true);
            if (bi.CanFitInInt64())
            {
                return(new CBORNumber(Kind.Integer, bi.ToInt64Checked()));
            }
            else
            {
                return(new CBORNumber(Kind.EInteger, bi));
            }
        }
Example #24
0
        public static object TypeToObject(
            CBORObject objThis,
            Type t,
            CBORTypeMapper mapper,
            PODOptions options,
            int depth)
        {
            if (t.Equals(typeof(int)))
            {
                return(objThis.AsInt32());
            }
            if (t.Equals(typeof(short)))
            {
                return(objThis.AsInt16());
            }
            if (t.Equals(typeof(ushort)))
            {
                return(objThis.AsUInt16());
            }
            if (t.Equals(typeof(byte)))
            {
                return(objThis.AsByte());
            }
            if (t.Equals(typeof(sbyte)))
            {
                return(objThis.AsSByte());
            }
            if (t.Equals(typeof(long)))
            {
                return(objThis.AsInt64());
            }
            if (t.Equals(typeof(uint)))
            {
                return(objThis.AsUInt32());
            }
            if (t.Equals(typeof(ulong)))
            {
                return(objThis.AsUInt64());
            }
            if (t.Equals(typeof(double)))
            {
                return(objThis.AsDouble());
            }
            if (t.Equals(typeof(decimal)))
            {
                return(objThis.AsDecimal());
            }
            if (t.Equals(typeof(float)))
            {
                return(objThis.AsSingle());
            }
            if (t.Equals(typeof(bool)))
            {
                return(objThis.AsBoolean());
            }
            if (t.Equals(typeof(char)))
            {
                if (objThis.Type == CBORType.TextString)
                {
                    string s = objThis.AsString();
                    if (s.Length != 1)
                    {
                        throw new CBORException("Can't convert to char");
                    }
                    return(s[0]);
                }
                if (objThis.IsIntegral && objThis.CanTruncatedIntFitInInt32())
                {
                    int c = objThis.AsInt32();
                    if (c < 0 || c >= 0x10000)
                    {
                        throw new CBORException("Can't convert to char");
                    }
                    return((char)c);
                }
                throw new CBORException("Can't convert to char");
            }
            if (t.Equals(typeof(DateTime)))
            {
                return(new CBORDateConverter().FromCBORObject(objThis));
            }
            if (t.Equals(typeof(Guid)))
            {
                return(new CBORUuidConverter().FromCBORObject(objThis));
            }
            if (t.Equals(typeof(Uri)))
            {
                return(new CBORUriConverter().FromCBORObject(objThis));
            }
            if (t.Equals(typeof(EDecimal)))
            {
                return(objThis.AsEDecimal());
            }
            if (t.Equals(typeof(EFloat)))
            {
                return(objThis.AsEFloat());
            }
            if (t.Equals(typeof(EInteger)))
            {
                return(objThis.AsEInteger());
            }
            if (t.Equals(typeof(ERational)))
            {
                return(objThis.AsERational());
            }
            if (IsAssignableFrom(typeof(Enum), t))
            {
                return(ObjectToEnum(objThis, t));
            }
            if (objThis.Type == CBORType.ByteString)
            {
                if (t.Equals(typeof(byte[])))
                {
                    byte[] bytes   = objThis.GetByteString();
                    var    byteret = new byte[bytes.Length];
                    Array.Copy(bytes, 0, byteret, 0, byteret.Length);
                    return(byteret);
                }
            }
            if (objThis.Type == CBORType.Array)
            {
                Type   objectType = typeof(object);
                var    isList     = false;
                object listObject = null;
#if NET40 || NET20
                if (IsAssignableFrom(typeof(Array), t))
                {
                    Type  elementType = t.GetElementType();
                    Array array       = Array.CreateInstance(
                        elementType,
                        GetDimensions(objThis));
                    return(FillArray(array, elementType, objThis, mapper, options, depth));
                }
                if (t.IsGenericType)
                {
                    Type td = t.GetGenericTypeDefinition();
                    isList = td.Equals(typeof(List <>)) || td.Equals(typeof(IList <>)) ||
                             td.Equals(typeof(ICollection <>)) ||
                             td.Equals(typeof(IEnumerable <>));
                }
                isList = isList && t.GetGenericArguments().Length == 1;
                if (isList)
                {
                    objectType = t.GetGenericArguments()[0];
                    Type listType = typeof(List <>).MakeGenericType(objectType);
                    listObject = Activator.CreateInstance(listType);
                }
#else
                if (IsAssignableFrom(typeof(Array), t))
                {
                    Type  elementType = t.GetElementType();
                    Array array       = Array.CreateInstance(
                        elementType,
                        GetDimensions(objThis));
                    return(FillArray(array, elementType, objThis, mapper, options, depth));
                }
                if (t.GetTypeInfo().IsGenericType)
                {
                    Type td = t.GetGenericTypeDefinition();
                    isList = (td.Equals(typeof(List <>)) ||
                              td.Equals(typeof(IList <>)) ||
                              td.Equals(typeof(ICollection <>)) ||
                              td.Equals(typeof(IEnumerable <>)));
                }
                isList = (isList && t.GenericTypeArguments.Length == 1);
                if (isList)
                {
                    objectType = t.GenericTypeArguments[0];
                    Type listType = typeof(List <>).MakeGenericType(objectType);
                    listObject = Activator.CreateInstance(listType);
                }
#endif
                if (listObject == null)
                {
                    if (t.Equals(typeof(IList)) ||
                        t.Equals(typeof(ICollection)) || t.Equals(typeof(IEnumerable)))
                    {
                        listObject = new List <object>();
                        objectType = typeof(object);
                    }
                }
                if (listObject != null)
                {
                    System.Collections.IList ie = (System.Collections.IList)listObject;
                    foreach (CBORObject value in objThis.Values)
                    {
                        ie.Add(value.ToObject(objectType, mapper, options, depth + 1));
                    }
                    return(listObject);
                }
            }
            if (objThis.Type == CBORType.Map)
            {
                var    isDict     = false;
                Type   keyType    = null;
                Type   valueType  = null;
                object dictObject = null;
#if NET40 || NET20
                isDict = t.IsGenericType;
                if (t.IsGenericType)
                {
                    Type td = t.GetGenericTypeDefinition();
                    isDict = td.Equals(typeof(Dictionary <,>)) ||
                             td.Equals(typeof(IDictionary <,>));
                }
                // DebugUtility.Log("list=" + isDict);
                isDict = isDict && t.GetGenericArguments().Length == 2;
                // DebugUtility.Log("list=" + isDict);
                if (isDict)
                {
                    keyType   = t.GetGenericArguments()[0];
                    valueType = t.GetGenericArguments()[1];
                    Type listType = typeof(Dictionary <,>).MakeGenericType(
                        keyType,
                        valueType);
                    dictObject = Activator.CreateInstance(listType);
                }
#else
                isDict = (t.GetTypeInfo().IsGenericType);
                if (t.GetTypeInfo().IsGenericType)
                {
                    Type td = t.GetGenericTypeDefinition();
                    isDict = (td.Equals(typeof(Dictionary <,>)) ||
                              td.Equals(typeof(IDictionary <,>)));
                }
                //DebugUtility.Log("list=" + isDict);
                isDict = (isDict && t.GenericTypeArguments.Length == 2);
                //DebugUtility.Log("list=" + isDict);
                if (isDict)
                {
                    keyType   = t.GenericTypeArguments[0];
                    valueType = t.GenericTypeArguments[1];
                    Type listType = typeof(Dictionary <,>).MakeGenericType(
                        keyType,
                        valueType);
                    dictObject = Activator.CreateInstance(listType);
                }
#endif
                if (dictObject == null)
                {
                    if (t.Equals(typeof(IDictionary)))
                    {
                        dictObject = new Dictionary <object, object>();
                        keyType    = typeof(object);
                        valueType  = typeof(object);
                    }
                }
                if (dictObject != null)
                {
                    System.Collections.IDictionary idic =
                        (System.Collections.IDictionary)dictObject;
                    foreach (CBORObject key in objThis.Keys)
                    {
                        CBORObject value = objThis[key];
                        idic.Add(
                            key.ToObject(keyType, mapper, options, depth + 1),
                            value.ToObject(valueType, mapper, options, depth + 1));
                    }
                    return(dictObject);
                }
                if (mapper != null)
                {
                    if (!mapper.FilterTypeName(t.FullName))
                    {
                        throw new CBORException("Type " + t.FullName +
                                                " not supported");
                    }
                }
                else
                {
                    if (t.FullName != null && (StartsWith(t.FullName, "Microsoft.Win32."
                                                          ) ||
                                               StartsWith(t.FullName, "System.IO.")))
                    {
                        throw new CBORException("Type " + t.FullName +
                                                " not supported");
                    }
                    if (StartsWith(t.FullName, "System.") &&
                        !HasCustomAttribute(t, "System.SerializableAttribute"))
                    {
                        throw new CBORException("Type " + t.FullName +
                                                " not supported");
                    }
                }
                var values = new List <KeyValuePair <string, CBORObject> >();
                foreach (string key in PropertyMap2.GetPropertyNames(
                             t,
                             options != null ? options.UseCamelCase : true))
                {
                    if (objThis.ContainsKey(key))
                    {
                        CBORObject cborValue = objThis[key];
                        var        dict      = new KeyValuePair <string, CBORObject>(
                            key,
                            cborValue);
                        values.Add(dict);
                    }
                }
                return(PropertyMap2.ObjectWithProperties(
                           t,
                           values,
                           mapper,
                           options,
                           depth));
            }
            else
            {
                throw new CBORException();
            }
        }
Example #25
0
        public CBORObject ReadForFirstByte(
            int firstbyte,
            CBORTypeFilter filter)
        {
            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;
            int expectedLength = CBORObject.GetExpectedLength(firstbyte);

            // Data checks
            if (expectedLength == -1)
            {
                // if the head byte is invalid
                throw new CBORException("Unexpected data encountered");
            }
            if (filter != null)
            {
                // Check for valid major types if asked
                if (!filter.MajorTypeMatches(type))
                {
                    throw new CBORException("Unexpected data type encountered");
                }
                if (firstbyte >= 0xe0 && firstbyte <= 0xff && firstbyte != 0xf9 &&
                    firstbyte != 0xfa && firstbyte != 0xfb)
                {
                    if (!filter.NonFPSimpleValueAllowed())
                    {
                        throw new CBORException("Unexpected data type encountered");
                    }
                }
            }
            // Check if this represents a fixed object
            CBORObject 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);
            }
            var      uadditional      = (long)additional;
            EInteger bigintAdditional = EInteger.Zero;
            var      hasBigAdditional = false;

            data = new byte[8];
            var lowAdditional = 0;

            switch (firstbyte & 0x1f)
            {
            case 24: {
                int tmp = this.stream.ReadByte();
                if (tmp < 0)
                {
                    throw new CBORException("Premature end of data");
                }
                lowAdditional = tmp;
                uadditional   = lowAdditional;
                break;
            }

            case 25: {
                if (this.stream.Read(data, 0, 2) != 2)
                {
                    throw new CBORException("Premature end of data");
                }
                lowAdditional  = ((int)(data[0] & (int)0xff)) << 8;
                lowAdditional |= (int)(data[1] & (int)0xff);
                uadditional    = lowAdditional;
                break;
            }

            case 26: {
                if (this.stream.Read(data, 0, 4) != 4)
                {
                    throw new CBORException("Premature end of data");
                }
                uadditional  = ((long)(data[0] & (long)0xff)) << 24;
                uadditional |= ((long)(data[1] & (long)0xff)) << 16;
                uadditional |= ((long)(data[2] & (long)0xff)) << 8;
                uadditional |= (long)(data[3] & (long)0xff);
                break;
            }

            case 27: {
                if (this.stream.Read(data, 0, 8) != 8)
                {
                    throw new CBORException("Premature end of data");
                }
                if ((((int)data[0]) & 0x80) != 0)
                {
                    // Won't fit in a signed 64-bit number
                    var uabytes = new byte[9];
                    uabytes[0]       = data[7];
                    uabytes[1]       = data[6];
                    uabytes[2]       = data[5];
                    uabytes[3]       = data[4];
                    uabytes[4]       = data[3];
                    uabytes[5]       = data[2];
                    uabytes[6]       = data[1];
                    uabytes[7]       = data[0];
                    uabytes[8]       = 0;
                    hasBigAdditional = true;
                    bigintAdditional = EInteger.FromBytes(uabytes, true);
                }
                else
                {
                    uadditional  = ((long)(data[0] & (long)0xff)) << 56;
                    uadditional |= ((long)(data[1] & (long)0xff)) << 48;
                    uadditional |= ((long)(data[2] & (long)0xff)) << 40;
                    uadditional |= ((long)(data[3] & (long)0xff)) << 32;
                    uadditional |= ((long)(data[4] & (long)0xff)) << 24;
                    uadditional |= ((long)(data[5] & (long)0xff)) << 16;
                    uadditional |= ((long)(data[6] & (long)0xff)) << 8;
                    uadditional |= (long)(data[7] & (long)0xff);
                }
                break;
            }
            }
            // 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) // Byte string
            {
                if (additional == 31)
                {
                    // 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" + ToUnsignedBigInteger(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 than supported ");
                        }
                        data = ms.ToArray();
                        return(new CBORObject(
                                   CBORObject.CBORObjectTypeByteString,
                                   data));
                    }
                }
                else
                {
                    if (hasBigAdditional)
                    {
                        throw new CBORException("Length of " +
                                                CBORUtilities.BigIntToString(bigintAdditional) + " is bigger than supported");
                    }
                    if (uadditional > Int32.MaxValue)
                    {
                        throw new CBORException("Length of " +
                                                CBORUtilities.LongToString(uadditional) +
                                                " is bigger than supported");
                    }
                    data = ReadByteData(this.stream, uadditional, null);
                    var cbor = new CBORObject(CBORObject.CBORObjectTypeByteString, data);
                    if (this.stringRefs != null)
                    {
                        int hint = (uadditional > Int32.MaxValue || hasBigAdditional) ?
                                   Int32.MaxValue : (int)uadditional;
                        this.stringRefs.AddStringIfNeeded(cbor, hint);
                    }
                    return(cbor);
                }
            }
            if (type == 3) // Text string
            {
                if (additional == 31)
                {
                    // 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" + ToUnsignedBigInteger(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(new CBORObject(
                               CBORObject.CBORObjectTypeTextString,
                               builder.ToString()));
                }
                else
                {
                    if (hasBigAdditional)
                    {
                        throw new CBORException("Length of " +
                                                CBORUtilities.BigIntToString(bigintAdditional) + " is bigger than supported");
                    }
                    if (uadditional > Int32.MaxValue)
                    {
                        throw new CBORException("Length of " +
                                                CBORUtilities.LongToString(uadditional) +
                                                " is bigger than supported");
                    }
                    if (PropertyMap.ExceedsKnownLength(this.stream, uadditional))
                    {
                        throw new CBORException("Premature end of data");
                    }
                    var builder = new StringBuilder();
                    switch (
                        DataUtilities.ReadUtf8(
                            this.stream,
                            (int)uadditional,
                            builder,
                            false))
                    {
                    case -1:
                        throw new CBORException("Invalid UTF-8");

                    case -2:
                        throw new CBORException("Premature end of data");
                    }
                    var cbor = new CBORObject(
                        CBORObject.CBORObjectTypeTextString,
                        builder.ToString());
                    if (this.stringRefs != null)
                    {
                        int hint = (uadditional > Int32.MaxValue || hasBigAdditional) ?
                                   Int32.MaxValue : (int)uadditional;
                        this.stringRefs.AddStringIfNeeded(cbor, hint);
                    }
                    return(cbor);
                }
            }
            if (type == 4) // Array
            {
                CBORObject cbor = CBORObject.NewArray();
                if (additional == 31)
                {
                    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;
                        }
                        if (filter != null && !filter.ArrayIndexAllowed(vtindex))
                        {
                            throw new CBORException("Array is too long");
                        }
                        ++this.depth;
                        CBORObject o = this.ReadForFirstByte(
                            headByte,
                            filter == null ? null : filter.GetSubFilter(vtindex));
                        --this.depth;
                        cbor.Add(o);
                        ++vtindex;
                    }
                    return(cbor);
                }
                if (hasBigAdditional)
                {
                    throw new CBORException("Length of " +
                                            CBORUtilities.BigIntToString(bigintAdditional) + " is bigger than supported");
                }
                if (uadditional > Int32.MaxValue)
                {
                    throw new CBORException("Length of " +
                                            CBORUtilities.LongToString(uadditional) +
                                            " is bigger than supported");
                }
                if (filter != null && !filter.ArrayLengthMatches(uadditional))
                {
                    throw new CBORException("Array is too long");
                }
                if (PropertyMap.ExceedsKnownLength(this.stream, uadditional))
                {
                    throw new CBORException("Remaining data too small for array length");
                }
                ++this.depth;
                for (long i = 0; i < uadditional; ++i)
                {
                    cbor.Add(
                        this.Read(filter == null ? null : filter.GetSubFilter(i)));
                }
                --this.depth;
                return(cbor);
            }
            if (type == 5) // Map, type 5
            {
                CBORObject cbor = CBORObject.NewMap();
                if (additional == 31)
                {
                    // 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, null);
                        CBORObject value = this.Read(null);
                        --this.depth;
                        if (this.policy == CBORDuplicatePolicy.Disallow)
                        {
                            if (cbor.ContainsKey(key))
                            {
                                throw new CBORException("Duplicate key already exists: " + key);
                            }
                        }
                        cbor[key] = value;
                    }
                    return(cbor);
                }
                if (hasBigAdditional)
                {
                    throw new CBORException("Length of " +
                                            CBORUtilities.BigIntToString(bigintAdditional) + " is bigger than supported");
                }
                if (uadditional > Int32.MaxValue)
                {
                    throw new CBORException("Length of " +
                                            CBORUtilities.LongToString(uadditional) +
                                            " is bigger than supported");
                }
                if (PropertyMap.ExceedsKnownLength(this.stream, uadditional))
                {
                    throw new CBORException("Remaining data too small for map length");
                }
                for (long i = 0; i < uadditional; ++i)
                {
                    ++this.depth;
                    CBORObject key   = this.Read(null);
                    CBORObject value = this.Read(null);
                    --this.depth;
                    if (this.policy == CBORDuplicatePolicy.Disallow)
                    {
                        if (cbor.ContainsKey(key))
                        {
                            throw new CBORException("Duplicate key already exists: " + key);
                        }
                    }
                    cbor[key] = value;
                }
                return(cbor);
            }
            if (type == 6) // Tagged item
            {
                ICBORTag taginfo       = null;
                var      haveFirstByte = false;
                var      newFirstByte  = -1;
                if (!hasBigAdditional)
                {
                    if (filter != null && !filter.TagAllowed(uadditional))
                    {
                        throw new CBORException("Unexpected tag encountered: " +
                                                uadditional);
                    }
                    int uad = uadditional >= 257 ? 257 : (uadditional < 0 ? 0 :
                                                          (int)uadditional);
                    switch (uad)
                    {
                    case 256:
                        // Tag 256: String namespace
                        this.stringRefs = this.stringRefs ?? (new StringRefs());
                        this.stringRefs.Push();
                        break;

                    case 25:
                        // String reference
                        if (this.stringRefs == null)
                        {
                            throw new CBORException("No stringref namespace");
                        }
                        break;

                    case 28:
                    case 29:
                        this.hasSharableObjects = true;
                        break;
                    }

                    taginfo = CBORObject.FindTagConverterLong(uadditional);
                }
                else
                {
                    if (filter != null && !filter.TagAllowed(bigintAdditional))
                    {
                        throw new CBORException("Unexpected tag encountered: " +
                                                uadditional);
                    }
                    taginfo = CBORObject.FindTagConverter(bigintAdditional);
                }
                ++this.depth;
                CBORObject o = haveFirstByte ? this.ReadForFirstByte(
                    newFirstByte,
                    taginfo == null ? null : taginfo.GetTypeFilter()) :
                               this.Read(taginfo == null ? null : taginfo.GetTypeFilter());
                --this.depth;
                if (hasBigAdditional)
                {
                    return(CBORObject.FromObjectAndTag(o, bigintAdditional));
                }
                if (uadditional < 65536)
                {
                    int uaddl = uadditional >= 257 ? 257 : (uadditional < 0 ? 0 :
                                                            (int)uadditional);
                    switch (uaddl)
                    {
                    case 256:
                        // string tag
                        this.stringRefs.Pop();
                        break;

                    case 25:
                        // stringref tag
                        return(this.stringRefs.GetString(o.AsEInteger()));
                    }

                    return(CBORObject.FromObjectAndTag(
                               o,
                               (int)uadditional));
                }
                return(CBORObject.FromObjectAndTag(
                           o,
                           (EInteger)uadditional));
            }
            throw new CBORException("Unexpected data encountered");
        }
Example #26
0
 private static bool IsUntaggedInteger(CBORObject o)
 {
     return(!o.IsTagged && o.Type == CBORType.Integer);
 }
        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");
        }
Example #28
0
 private static bool IsUntaggedIntegerOrBignum(CBORObject o)
 {
     return(IsUntaggedInteger(o) || ((o.HasOneTag(2) || o.HasOneTag(3)) &&
                                     o.Type == CBORType.ByteString));
 }
        private CBORObject NextJSONValue(
            int firstChar,
            int[] nextChar,
            int depth)
        {
            string     str;
            int        c   = firstChar;
            CBORObject obj = null;

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

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

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

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

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

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

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

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

            default: this.RaiseError("Value can't be parsed.");
                break;
            }
            return(null);
        }
Example #30
0
 public CBORObject ValidateObject(CBORObject obj)
 {
     return CBORTag2.ConvertToBigNum(obj, true);
 }
Example #31
0
        public static CBORObject Multiply(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException(nameof(a));
            }
            if (b == null)
            {
                throw new ArgumentNullException(nameof(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));
            }
        }
Example #32
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         = CBORDataUtilities.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 #33
0
 public static CBORObject FromObject(ulong value)
 {
     return(CBORObject.FromObject(UInt64ToEInteger(value)));
 }
Example #34
0
        private static CBORNumber BigFracToNumber(
            CBORObject o,
            int tagName)
        {
            if (o.Type != CBORType.Array)
            {
                return(null); // "Big fraction must be an array");
            }
            if (tagName == 268 || tagName == 269)
            {
                if (o.Count != 3)
                {
                    return(null); // "Extended big fraction requires exactly 3 items");
                }
                if (!IsUntaggedInteger(o[2]))
                {
                    return(null); // "Third item must be an integer");
                }
            }
            else
            {
                if (o.Count != 2)
                {
                    return(null); // "Big fraction requires exactly 2 items");
                }
            }
            if (tagName == 4 || tagName == 5)
            {
                if (!IsUntaggedInteger(o[0]))
                {
                    return(null); // "Exponent is not an integer");
                }
            }
            else
            {
                if (!IsUntaggedIntegerOrBignum(o[0]))
                {
                    return(null); // "Exponent is not an integer or bignum");
                }
            }
            if (!IsUntaggedIntegerOrBignum(o[1]))
            {
                return(null); // "Mantissa is not an integer or bignum");
            }
            EInteger exponent = IntegerOrBignum(o[0]);
            EInteger mantissa = IntegerOrBignum(o[1]);
            bool     isdec    = tagName == 4 || tagName == 264 || tagName == 268;
            EDecimal edec     = isdec ? EDecimal.Create(mantissa, exponent) : null;
            EFloat   efloat   = !isdec?EFloat.Create(mantissa, exponent) : null;

            if (tagName == 268 || tagName == 269)
            {
                if (mantissa.Sign < 0)
                {
                    return(null); // "Mantissa may not be negative");
                }
                if (!o[2].CanValueFitInInt32())
                {
                    return(null); // "Invalid options");
                }
                int options = o[2].AsInt32Value();
                switch (options)
                {
                case 0:
                    break;

                case 1:
                    if (isdec)
                    {
                        edec = edec.Negate();
                    }
                    else
                    {
                        efloat = efloat.Negate();
                    }
                    break;

                case 2:
                    if (!exponent.IsZero || !mantissa.IsZero)
                    {
                        return(null); // "invalid values");
                    }
                    if (isdec)
                    {
                        edec = EDecimal.PositiveInfinity;
                    }
                    else
                    {
                        efloat = EFloat.PositiveInfinity;
                    }
                    break;

                case 3:
                    if (!exponent.IsZero || !mantissa.IsZero)
                    {
                        return(null); // "invalid values");
                    }
                    if (isdec)
                    {
                        edec = EDecimal.NegativeInfinity;
                    }
                    else
                    {
                        efloat = EFloat.NegativeInfinity;
                    }
                    break;

                case 4:
                case 5:
                case 6:
                case 7:
                    if (!exponent.IsZero)
                    {
                        return(null); // "invalid values");
                    }
                    if (isdec)
                    {
                        edec = EDecimal.CreateNaN(
                            mantissa,
                            options >= 6,
                            options == 5 || options == 7,
                            null);
                    }
                    else
                    {
                        efloat = EFloat.CreateNaN(
                            mantissa,
                            options >= 6,
                            options == 5 || options == 7,
                            null);
                    }
                    break;

                default: return(null); // "Invalid options");
                }
            }
            if (isdec)
            {
                return(CBORNumber.FromObject(edec));
            }
            else
            {
                return(CBORNumber.FromObject(efloat));
            }
        }
Example #35
0
        private static CBORNumber RationalToNumber(
            CBORObject o,
            int tagName)
        {
            if (o.Type != CBORType.Array)
            {
                return(null); // "Big fraction must be an array";
            }
            if (tagName == 270)
            {
                if (o.Count != 3)
                {
                    return(null); // "Extended big fraction requires exactly 3 items";
                }
                if (!IsUntaggedInteger(o[2]))
                {
                    return(null); // "Third item must be an integer";
                }
            }
            else
            {
                if (o.Count != 2)
                {
                    return(null); // "Big fraction requires exactly 2 items";
                }
            }
            if (!IsUntaggedIntegerOrBignum(o[0]))
            {
                return(null); // "Numerator is not an integer or bignum";
            }
            if (!IsUntaggedIntegerOrBignum(o[1]))
            {
                return(null); // "Denominator is not an integer or bignum");
            }
            EInteger numerator   = IntegerOrBignum(o[0]);
            EInteger denominator = IntegerOrBignum(o[1]);

            if (denominator.Sign <= 0)
            {
                return(null); // "Denominator may not be negative or zero");
            }
            ERational erat = ERational.Create(numerator, denominator);

            if (tagName == 270)
            {
                if (numerator.Sign < 0)
                {
                    return(null); // "Numerator may not be negative");
                }
                if (!o[2].CanValueFitInInt32())
                {
                    return(null); // "Invalid options";
                }
                int options = o[2].AsInt32Value();
                switch (options)
                {
                case 0:
                    break;

                case 1:
                    erat = erat.Negate();
                    break;

                case 2:
                    if (!numerator.IsZero || denominator.CompareTo(1) != 0)
                    {
                        return(null); // "invalid values");
                    }
                    erat = ERational.PositiveInfinity;
                    break;

                case 3:
                    if (!numerator.IsZero || denominator.CompareTo(1) != 0)
                    {
                        return(null); // "invalid values");
                    }
                    erat = ERational.NegativeInfinity;
                    break;

                case 4:
                case 5:
                case 6:
                case 7:
                    if (denominator.CompareTo(1) != 0)
                    {
                        return(null); // "invalid values");
                    }
                    erat = ERational.CreateNaN(
                        numerator,
                        options >= 6,
                        options == 5 || options == 7);
                    break;

                default: return(null); // "Invalid options");
                }
            }
            return(CBORNumber.FromObject(erat));
        }
Example #36
0
        public static CBORObject Divide(CBORObject a, CBORObject b)
        {
            if (a == null)
            {
                throw new ArgumentNullException(nameof(a));
            }
            if (b == null)
            {
                throw new ArgumentNullException(nameof(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)));
            }
        }
Example #37
0
 public ParticipantObject(CBORObject cborObject)
 {
     _jsonString = cborObject.ToJSONString();
 }
Example #38
0
        private static bool CheckRationalToNumber(
            CBORObject o,
            int tagName)
        {
            if (o.Type != CBORType.Array)
            {
                return(false);
            }
            if (tagName == 270)
            {
                if (o.Count != 3)
                {
                    return(false);
                }
                if (!IsUntaggedInteger(o[2]))
                {
                    return(false);
                }
            }
            else
            {
                if (o.Count != 2)
                {
                    return(false);
                }
            }
            if (!IsUntaggedIntegerOrBignum(o[0]))
            {
                return(false);
            }
            if (!IsUntaggedIntegerOrBignum(o[1]))
            {
                return(false);
            }
            EInteger denominator = IntegerOrBignum(o[1]);

            if (denominator.Sign <= 0)
            {
                return(false);
            }
            if (tagName == 270)
            {
                EInteger numerator = IntegerOrBignum(o[0]);
                if (numerator.Sign < 0 || !o[2].CanValueFitInInt32())
                {
                    return(false);
                }
                int options = o[2].AsInt32Value();
                switch (options)
                {
                case 0:
                case 1:
                    return(true);

                case 2:
                case 3:
                    return(numerator.IsZero && denominator.CompareTo(1) == 0);

                case 4:
                case 5:
                case 6:
                case 7:
                    return(denominator.CompareTo(1) == 0);

                default: return(false);
                }
            }
            return(true);
        }
Example #39
0
        private static bool CheckBigFracToNumber(
            CBORObject o,
            int tagName)
        {
            if (o.Type != CBORType.Array)
            {
                return(false);
            }
            if (tagName == 268 || tagName == 269)
            {
                if (o.Count != 3)
                {
                    return(false);
                }
                if (!IsUntaggedInteger(o[2]))
                {
                    return(false);
                }
            }
            else
            {
                if (o.Count != 2)
                {
                    return(false);
                }
            }
            if (tagName == 4 || tagName == 5)
            {
                if (!IsUntaggedInteger(o[0]))
                {
                    return(false);
                }
            }
            else
            {
                if (!IsUntaggedIntegerOrBignum(o[0]))
                {
                    return(false);
                }
            }
            if (!IsUntaggedIntegerOrBignum(o[1]))
            {
                return(false);
            }
            if (tagName == 268 || tagName == 269)
            {
                EInteger exponent = IntegerOrBignum(o[0]);
                EInteger mantissa = IntegerOrBignum(o[1]);
                if (mantissa.Sign < 0 || !o[2].CanValueFitInInt32())
                {
                    return(false);
                }
                int options = o[2].AsInt32Value();
                switch (options)
                {
                case 0:
                case 1:
                    return(true);

                case 2:
                case 3:
                    return(exponent.IsZero && mantissa.IsZero);

                case 4:
                case 5:
                case 6:
                case 7:
                    return(exponent.IsZero);

                default: return(false);
                }
            }
            return(true);
        }
Example #40
0
 public CBORObject ValidateObject(CBORObject obj)
 {
     return CBORTag5.ConvertToDecimalFrac(obj, true, this.extended);
 }