public static CBORObject FromArray( Object arrObj, PODOptions options) { var arr = (Array)arrObj; int rank = arr.Rank; if (rank == 0) { return(CBORObject.NewArray()); } CBORObject obj = null; if (rank == 1) { // Most common case: the array is one-dimensional obj = CBORObject.NewArray(); int len = arr.GetLength(0); for (var i = 0; i < len; ++i) { obj.Add( CBORObject.FromObject( arr.GetValue(i), options)); } return(obj); } var index = new int[rank]; var dimensions = new int[rank]; for (var i = 0; i < rank; ++i) { dimensions[i] = arr.GetLength(i); } if (!FirstElement(index, dimensions)) { return(obj); } obj = BuildCBORArray(dimensions); do { CBORObject o = CBORObject.FromObject( arr.GetValue(index), options); SetCBORObject(obj, index, o); } while (NextElement(index, dimensions)); return(obj); }
private static CBORObject FromObjectAndInnerTags( object objectValue, CBORObject objectWithTags) { CBORObject newObject = CBORObject.FromObject(objectValue); if (!objectWithTags.IsTagged) { return(newObject); } objectWithTags = objectWithTags.UntagOne(); if (!objectWithTags.IsTagged) { return(newObject); } EInteger[] tags = objectWithTags.GetAllTags(); for (int i = tags.Length - 1; i >= 0; --i) { newObject = CBORObject.FromObjectAndTag(newObject, tags[i]); } return(newObject); }
internal static CBORObject ParseSmallNumber(int digit, JSONOptions options) { #if DEBUG if (digit < 0) { throw new ArgumentException("digit (" + digit + ") is not greater" + "\u0020or equal to 0"); } #endif if (options != null && options.NumberConversion == JSONOptions.ConversionMode.Double) { return(CBORObject.FromObject((double)digit)); } else { // NOTE: Assumes digit is nonnegative, so PreserveNegativeZeros is irrelevant return(CBORObject.FromObject(digit)); } }
internal static CBORObject ConvertToDecimalFrac( CBORObject o, bool isDecimal, bool extended) { if (o.Type != CBORType.Array) { throw new CBORException("Big fraction must be an array"); } if (o.Count != 2) { throw new CBORException("Big fraction requires exactly 2 items"); } if (!o[0].IsIntegral) { throw new CBORException("Exponent is not an integer"); } if (!o[1].IsIntegral) { throw new CBORException("Mantissa is not an integer"); } EInteger exponent = o[0].AsEInteger(); EInteger mantissa = o[1].AsEInteger(); if (exponent.GetSignedBitLength() > 64 && !extended) { throw new CBORException("Exponent is too big"); } if (exponent.IsZero) { // Exponent is 0, so return mantissa instead return(CBORObject.FromObject(mantissa)); } // NOTE: Discards tags. See comment in CBORTag2. return(isDecimal ? CBORObject.FromObject(EDecimal.Create(mantissa, exponent)) : CBORObject.FromObject(EFloat.Create(mantissa, exponent))); }
public CBORObject GetString(long smallIndex) { if (smallIndex < 0) { throw new CBORException("Unexpected index"); } if (smallIndex > Int32.MaxValue) { throw new CBORException("Index " + smallIndex + " is bigger than supported "); } var index = (int)smallIndex; List <CBORObject> lastList = this.stack[this.stack.Count - 1]; if (index >= lastList.Count) { throw new CBORException("Index " + index + " is not valid"); } CBORObject ret = lastList[index]; // Byte strings are mutable, so make a copy return((ret.Type == CBORType.ByteString) ? CBORObject.FromObject(ret.GetByteString()) : ret); }
public CBORObject GetString(EInteger bigIndex) { if (bigIndex.Sign < 0) { throw new CBORException("Unexpected index"); } if (!bigIndex.CanFitInInt32()) { throw new CBORException("Index " + bigIndex + " is bigger than supported "); } var index = (int)bigIndex; List <CBORObject> lastList = this.stack[this.stack.Count - 1]; if (index >= lastList.Count) { throw new CBORException("Index " + index + " is not valid"); } CBORObject ret = lastList[index]; // Byte strings are mutable, so make a copy return((ret.Type == CBORType.ByteString) ? CBORObject.FromObject(ret.GetByteString()) : ret); }
public static CBORObject Remainder(CBORObject a, CBORObject b) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (a.Type != CBORType.Number) { throw new ArgumentException("a.Type (" + a.Type + ") is not equal to " + CBORType.Number); } if (b.Type != CBORType.Number) { throw new ArgumentException("b.Type (" + b.Type + ") is not equal to " + CBORType.Number); } object objA = a.ThisItem; object objB = b.ThisItem; int typeA = a.ItemType; int typeB = b.ItemType; if (typeA == CBORObject.CBORObjectTypeInteger && typeB == CBORObject.CBORObjectTypeInteger) { var valueA = (long)objA; var valueB = (long)objB; return((valueA == Int64.MinValue && valueB == -1) ? CBORObject.FromObject(0) : CBORObject.FromObject(valueA % valueB)); } if (typeA == CBORObject.CBORObjectTypeExtendedRational || typeB == CBORObject.CBORObjectTypeExtendedRational) { ERational e1 = CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA); ERational e2 = CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB); return(CBORObject.FromObject(e1.Remainder(e2))); } if (typeA == CBORObject.CBORObjectTypeExtendedDecimal || typeB == CBORObject.CBORObjectTypeExtendedDecimal) { EDecimal e1 = CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA); EDecimal e2 = CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB); return(CBORObject.FromObject(e1.Remainder(e2, null))); } if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB == CBORObject.CBORObjectTypeExtendedFloat || typeA == CBORObject.CBORObjectTypeDouble || typeB == CBORObject.CBORObjectTypeDouble || typeA == CBORObject.CBORObjectTypeSingle || typeB == CBORObject.CBORObjectTypeSingle) { EFloat e1 = CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA); EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB); return(CBORObject.FromObject(e1.Remainder(e2, null))); } else { EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA); EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB); return(CBORObject.FromObject(b1 % (EInteger)b2)); } }
public static CBORObject Divide(CBORObject a, CBORObject b) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (a.Type != CBORType.Number) { throw new ArgumentException("a.Type (" + a.Type + ") is not equal to " + CBORType.Number); } if (b.Type != CBORType.Number) { throw new ArgumentException("b.Type (" + b.Type + ") is not equal to " + CBORType.Number); } object objA = a.ThisItem; object objB = b.ThisItem; int typeA = a.ItemType; int typeB = b.ItemType; if (typeA == CBORObject.CBORObjectTypeInteger && typeB == CBORObject.CBORObjectTypeInteger) { var valueA = (long)objA; var valueB = (long)objB; if (valueB == 0) { return((valueA == 0) ? CBORObject.NaN : ((valueA < 0) ? CBORObject.NegativeInfinity : CBORObject.PositiveInfinity)); } if (valueA == Int64.MinValue && valueB == -1) { return(CBORObject.FromObject(valueA).Negate()); } long quo = valueA / valueB; long rem = valueA - (quo * valueB); return((rem == 0) ? CBORObject.FromObject(quo) : CBORObject.FromObject( ERational.Create( (EInteger)valueA, (EInteger)valueB))); } if (typeA == CBORObject.CBORObjectTypeExtendedRational || typeB == CBORObject.CBORObjectTypeExtendedRational) { ERational e1 = CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA); ERational e2 = CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB); return(CBORObject.FromObject(e1.Divide(e2))); } if (typeA == CBORObject.CBORObjectTypeExtendedDecimal || typeB == CBORObject.CBORObjectTypeExtendedDecimal) { EDecimal e1 = CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA); EDecimal e2 = CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB); if (e1.IsZero && e2.IsZero) { return(CBORObject.NaN); } EDecimal eret = e1.Divide(e2, null); // If either operand is infinity or NaN, the result // is already exact. Likewise if the result is a finite number. if (!e1.IsFinite || !e2.IsFinite || eret.IsFinite) { return(CBORObject.FromObject(eret)); } ERational er1 = CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA); ERational er2 = CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB); return(CBORObject.FromObject(er1.Divide(er2))); } if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB == CBORObject.CBORObjectTypeExtendedFloat || typeA == CBORObject.CBORObjectTypeDouble || typeB == CBORObject.CBORObjectTypeDouble || typeA == CBORObject.CBORObjectTypeSingle || typeB == CBORObject.CBORObjectTypeSingle) { EFloat e1 = CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA); EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB); if (e1.IsZero && e2.IsZero) { return(CBORObject.NaN); } EFloat eret = e1.Divide(e2, null); // If either operand is infinity or NaN, the result // is already exact. Likewise if the result is a finite number. if (!e1.IsFinite || !e2.IsFinite || eret.IsFinite) { return(CBORObject.FromObject(eret)); } ERational er1 = CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA); ERational er2 = CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB); return(CBORObject.FromObject(er1.Divide(er2))); } else { EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA); EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB); if (b2.IsZero) { return(b1.IsZero ? CBORObject.NaN : ((b1.Sign < 0) ? CBORObject.NegativeInfinity : CBORObject.PositiveInfinity)); } EInteger bigrem; EInteger bigquo; { EInteger[] divrem = b1.DivRem(b2); bigquo = divrem[0]; bigrem = divrem[1]; } return(bigrem.IsZero ? CBORObject.FromObject(bigquo) : CBORObject.FromObject(ERational.Create(b1, b2))); } }
public static CBORObject Multiply(CBORObject a, CBORObject b) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (a.Type != CBORType.Number) { throw new ArgumentException("a.Type (" + a.Type + ") is not equal to " + CBORType.Number); } if (b.Type != CBORType.Number) { throw new ArgumentException("b.Type (" + b.Type + ") is not equal to " + CBORType.Number); } object objA = a.ThisItem; object objB = b.ThisItem; int typeA = a.ItemType; int typeB = b.ItemType; if (typeA == CBORObject.CBORObjectTypeInteger && typeB == CBORObject.CBORObjectTypeInteger) { var valueA = (long)objA; var valueB = (long)objB; bool apos = valueA > 0L; bool bpos = valueB > 0L; if ( (apos && ((!bpos && (Int64.MinValue / valueA) > valueB) || (bpos && valueA > (Int64.MaxValue / valueB)))) || (!apos && ((!bpos && valueA != 0L && (Int64.MaxValue / valueA) > valueB) || (bpos && valueA < (Int64.MinValue / valueB))))) { // would overflow, convert to EInteger var bvalueA = (EInteger)valueA; var bvalueB = (EInteger)valueB; return(CBORObject.FromObject(bvalueA * (EInteger)bvalueB)); } return(CBORObject.FromObject(valueA * valueB)); } if (typeA == CBORObject.CBORObjectTypeExtendedRational || typeB == CBORObject.CBORObjectTypeExtendedRational) { ERational e1 = CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA); ERational e2 = CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB); return(CBORObject.FromObject(e1.Multiply(e2))); } if (typeA == CBORObject.CBORObjectTypeExtendedDecimal || typeB == CBORObject.CBORObjectTypeExtendedDecimal) { EDecimal e1 = CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA); EDecimal e2 = CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB); return(CBORObject.FromObject(e1.Multiply(e2))); } if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB == CBORObject.CBORObjectTypeExtendedFloat || typeA == CBORObject.CBORObjectTypeDouble || typeB == CBORObject.CBORObjectTypeDouble || typeA == CBORObject.CBORObjectTypeSingle || typeB == CBORObject.CBORObjectTypeSingle) { EFloat e1 = CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA); EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB); return(CBORObject.FromObject(e1.Multiply(e2))); } else { EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA); EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB); return(CBORObject.FromObject(b1 * (EInteger)b2)); } }
internal static CBORObject ParseJSONNumber( string chars, int offset, int count, JSONOptions options, int[] endOfNumber) { if (chars == null || chars.Length == 0 || count <= 0) { return(null); } if (offset < 0 || offset > chars.Length) { return(null); } if (count > chars.Length || chars.Length - offset < count) { return(null); } JSONOptions opt = options ?? CBORDataUtilities.DefaultOptions; bool preserveNegativeZero = options.PreserveNegativeZero; JSONOptions.ConversionMode kind = options.NumberConversion; int endPos = offset + count; int initialOffset = offset; var negative = false; if (chars[initialOffset] == '-') { ++offset; negative = true; } int numOffset = offset; var haveDecimalPoint = false; var haveDigits = false; var haveDigitsAfterDecimal = false; var haveExponent = false; int i = offset; var decimalPointPos = -1; // Check syntax int k = i; if (endPos - 1 > k && chars[k] == '0' && chars[k + 1] >= '0' && chars[k + 1] <= '9') { if (endOfNumber != null) { endOfNumber[0] = k + 2; } return(null); } for (; k < endPos; ++k) { char c = chars[k]; if (c >= '0' && c <= '9') { haveDigits = true; haveDigitsAfterDecimal |= haveDecimalPoint; } else if (c == '.') { if (!haveDigits || haveDecimalPoint) { // no digits before the decimal point, // or decimal point already seen if (endOfNumber != null) { endOfNumber[0] = k; } return(null); } haveDecimalPoint = true; decimalPointPos = k; } else if (c == 'E' || c == 'e') { ++k; haveExponent = true; break; } else { if (endOfNumber != null) { endOfNumber[0] = k; // Check if character can validly appear after a JSON number if (c != ',' && c != ']' && c != '}' && c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09) { return(null); } else { endPos = k; break; } } return(null); } } if (!haveDigits || (haveDecimalPoint && !haveDigitsAfterDecimal)) { if (endOfNumber != null) { endOfNumber[0] = k; } return(null); } var exponentPos = -1; var negativeExp = false; if (haveExponent) { haveDigits = false; if (k == endPos) { if (endOfNumber != null) { endOfNumber[0] = k; } return(null); } char c = chars[k]; if (c == '+') { ++k; } else if (c == '-') { negativeExp = true; ++k; } for (; k < endPos; ++k) { c = chars[k]; if (c >= '0' && c <= '9') { if (exponentPos < 0 && c != '0') { exponentPos = k; } haveDigits = true; } else if (endOfNumber != null) { endOfNumber[0] = k; // Check if character can validly appear after a JSON number if (c != ',' && c != ']' && c != '}' && c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09) { return(null); } else { endPos = k; break; } } else { return(null); } } if (!haveDigits) { if (endOfNumber != null) { endOfNumber[0] = k; } return(null); } } if (endOfNumber != null) { endOfNumber[0] = endPos; } if (exponentPos >= 0 && endPos - exponentPos > 20) { // Exponent too high for precision to overcome (which // has a length no bigger than Int32.MaxValue, which is 10 digits // long) if (negativeExp) { // underflow if (kind == JSONOptions.ConversionMode.Double || kind == JSONOptions.ConversionMode.IntOrFloat) { if (!negative) { return(CBORObject.FromFloatingPointBits(0, 2)); } else { return(CBORObject.FromFloatingPointBits(0x8000, 2)); } } else if (kind == JSONOptions.ConversionMode.IntOrFloatFromDouble) { return(CBORObject.FromObject(0)); } } else { // overflow if (kind == JSONOptions.ConversionMode.Double || kind == JSONOptions.ConversionMode.IntOrFloatFromDouble || kind == JSONOptions.ConversionMode.IntOrFloat) { return(CBORObject.FromFloatingPointBits( negative ? DoubleNegInfinity : DoublePosInfinity, 8)); } else if (kind == JSONOptions.ConversionMode.Decimal128) { return(CBORObject.FromObject(negative ? EDecimal.NegativeInfinity : EDecimal.PositiveInfinity)); } } } if (!haveExponent && !haveDecimalPoint && (endPos - numOffset) <= 16) { // Very common case of all-digit JSON number strings // less than 2^53 (with or without number sign) long v = 0L; int vi = numOffset; for (; vi < endPos; ++vi) { v = (v * 10) + (int)(chars[vi] - '0'); } if ((v != 0 || !negative) && v < (1L << 53) - 1) { if (negative) { v = -v; } if (kind == JSONOptions.ConversionMode.Double) { return(CBORObject.FromFloatingPointBits(EFloat.FromInt64(v).ToDoubleBits(), 8)); } else if (kind == JSONOptions.ConversionMode.Decimal128) { return(CBORObject.FromObject(EDecimal.FromInt64(v))); } else { return(CBORObject.FromObject(v)); } } } if (kind == JSONOptions.ConversionMode.Full) { if (!haveDecimalPoint && !haveExponent) { EInteger ei = EInteger.FromSubstring(chars, initialOffset, endPos); if (preserveNegativeZero && ei.IsZero && negative) { // TODO: In next major version, change to EDecimal.NegativeZero return(CBORObject.FromFloatingPointBits(0x8000, 2)); } return(CBORObject.FromObject(ei)); } if (!haveExponent && haveDecimalPoint) { // No more than 18 digits plus one decimal point (which // should fit a long) long lv = 0L; int expo = -(endPos - (decimalPointPos + 1)); int vi = numOffset; var digitCount = 0; for (; vi < decimalPointPos; ++vi) { if (digitCount < 0 || digitCount >= 18) { digitCount = -1; break; } else if (digitCount > 0 || chars[vi] != '0') { ++digitCount; } lv = checked ((lv * 10) + (int)(chars[vi] - '0')); } for (vi = decimalPointPos + 1; vi < endPos; ++vi) { if (digitCount < 0 || digitCount >= 18) { digitCount = -1; break; } else if (digitCount > 0 || chars[vi] != '0') { ++digitCount; } lv = checked ((lv * 10) + (int)(chars[vi] - '0')); } if (negative) { lv = -lv; } if (digitCount >= 0 && (!negative || lv != 0)) { if (expo == 0) { return(CBORObject.FromObject(lv)); } else { CBORObject cbor = CBORObject.FromArrayBackedObject( new CBORObject[] { CBORObject.FromObject(expo), CBORObject.FromObject(lv), }); return(cbor.WithTag(4)); } } } // DebugUtility.Log("convfull " + chars.Substring(initialOffset, endPos - // initialOffset)); EDecimal ed = EDecimal.FromString( chars, initialOffset, endPos - initialOffset); if (ed.IsZero && negative) { if (ed.Exponent.IsZero) { // TODO: In next major version, use EDecimal // for preserveNegativeZero return(preserveNegativeZero ? CBORObject.FromFloatingPointBits(0x8000, 2) : CBORObject.FromObject(0)); } else if (!preserveNegativeZero) { return(CBORObject.FromObject(ed.Negate())); } else { return(CBORObject.FromObject(ed)); } } else { return(ed.Exponent.IsZero ? CBORObject.FromObject(ed.Mantissa) : CBORObject.FromObject(ed)); } } else if (kind == JSONOptions.ConversionMode.Double) { EFloat ef = EFloat.FromString( chars, initialOffset, endPos - initialOffset, EContext.Binary64); long lb = ef.ToDoubleBits(); if (!preserveNegativeZero && (lb == 1L << 63 || lb == 0L)) { lb = 0L; } return(CBORObject.FromFloatingPointBits(lb, 8)); } else if (kind == JSONOptions.ConversionMode.Decimal128) { EDecimal ed = EDecimal.FromString( chars, initialOffset, endPos - initialOffset, EContext.Decimal128); if (!preserveNegativeZero && ed.IsNegative && ed.IsZero) { ed = ed.Negate(); } return(CBORObject.FromObject(ed)); } else if (kind == JSONOptions.ConversionMode.IntOrFloatFromDouble) { EFloat ef = EFloat.FromString( chars, initialOffset, endPos - initialOffset, EContext.Binary64); long lb = ef.ToDoubleBits(); return((!CBORUtilities.IsBeyondSafeRange(lb) && CBORUtilities.IsIntegerValue(lb)) ? CBORObject.FromObject(CBORUtilities.GetIntegerValue(lb)) : CBORObject.FromFloatingPointBits(lb, 8)); } else if (kind == JSONOptions.ConversionMode.IntOrFloat) { EContext ctx = EContext.Binary64.WithBlankFlags(); EFloat ef = EFloat.FromString( chars, initialOffset, endPos - initialOffset, ctx); long lb = ef.ToDoubleBits(); if ((ctx.Flags & EContext.FlagInexact) != 0) { // Inexact conversion to double, meaning that the string doesn't // represent an integer in [-(2^53)+1, 2^53), which is representable // exactly as double, so treat as ConversionMode.Double if (!preserveNegativeZero && (lb == 1L << 63 || lb == 0L)) { lb = 0L; } return(CBORObject.FromFloatingPointBits(lb, 8)); } else { // Exact conversion; treat as ConversionMode.IntToFloatFromDouble return((!CBORUtilities.IsBeyondSafeRange(lb) && CBORUtilities.IsIntegerValue(lb)) ? CBORObject.FromObject(CBORUtilities.GetIntegerValue(lb)) : CBORObject.FromFloatingPointBits(lb, 8)); } } else { throw new ArgumentException("Unsupported conversion kind."); } }
/// <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)); }
internal static CBORObject ParseJSONNumber( string str, int offset, int count, JSONOptions options, int[] endOfNumber) { if (String.IsNullOrEmpty(str) || count <= 0) { return(null); } if (offset < 0 || offset > str.Length) { return(null); } if (count > str.Length || str.Length - offset < count) { return(null); } JSONOptions opt = options ?? DefaultOptions; bool preserveNegativeZero = options.PreserveNegativeZero; JSONOptions.ConversionMode kind = options.NumberConversion; int endPos = offset + count; int initialOffset = offset; var negative = false; if (str[initialOffset] == '-') { ++offset; negative = true; } int numOffset = offset; var haveDecimalPoint = false; var haveDigits = false; var haveDigitsAfterDecimal = false; var haveExponent = false; int i = offset; var decimalPointPos = -1; // Check syntax int k = i; if (endPos - 1 > k && str[k] == '0' && str[k + 1] >= '0' && str[k + 1] <= '9') { if (endOfNumber != null) { endOfNumber[0] = k + 2; } return(null); } for (; k < endPos; ++k) { char c = str[k]; if (c >= '0' && c <= '9') { haveDigits = true; haveDigitsAfterDecimal |= haveDecimalPoint; } else if (c == '.') { if (!haveDigits || haveDecimalPoint) { // no digits before the decimal point, // or decimal point already seen if (endOfNumber != null) { endOfNumber[0] = k; } return(null); } haveDecimalPoint = true; decimalPointPos = k; } else if (c == 'E' || c == 'e') { ++k; haveExponent = true; break; } else { if (endOfNumber != null) { endOfNumber[0] = k; // Check if character can validly appear after a JSON number if (c != ',' && c != ']' && c != '}' && c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09) { return(null); } else { endPos = k; break; } } return(null); } } if (!haveDigits || (haveDecimalPoint && !haveDigitsAfterDecimal)) { if (endOfNumber != null) { endOfNumber[0] = k; } return(null); } if (haveExponent) { haveDigits = false; if (k == endPos) { if (endOfNumber != null) { endOfNumber[0] = k; } return(null); } char c = str[k]; if (c == '+' || c == '-') { ++k; } for (; k < endPos; ++k) { c = str[k]; if (c >= '0' && c <= '9') { haveDigits = true; } else if (endOfNumber != null) { endOfNumber[0] = k; // Check if character can validly appear after a JSON number if (c != ',' && c != ']' && c != '}' && c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09) { return(null); } else { endPos = k; break; } } else { return(null); } } if (!haveDigits) { if (endOfNumber != null) { endOfNumber[0] = k; } return(null); } } if (endOfNumber != null) { endOfNumber[0] = endPos; } if (!haveExponent && !haveDecimalPoint && (endPos - numOffset) <= 16) { // Very common case of all-digit JSON number strings // less than 2^53 (with or without number sign) long v = 0L; int vi = numOffset; for (; vi < endPos; ++vi) { v = (v * 10) + (int)(str[vi] - '0'); } if ((v != 0 || !negative) && v < (1L << 53) - 1) { if (negative) { v = -v; } if (kind == JSONOptions.ConversionMode.Double) { return(CBORObject.FromObject((double)v)); } else if (kind == JSONOptions.ConversionMode.Decimal128) { return(CBORObject.FromObject(EDecimal.FromInt64(v))); } else { return(CBORObject.FromObject(v)); } } } if (kind == JSONOptions.ConversionMode.Full) { if (!haveDecimalPoint && !haveExponent) { EInteger ei = EInteger.FromSubstring(str, initialOffset, endPos); if (preserveNegativeZero && ei.IsZero && negative) { // TODO: In next major version, change to EDecimal.NegativeZero return(CBORObject.FromFloatingPointBits(0x8000, 2)); } return(CBORObject.FromObject(ei)); } if (!haveExponent && haveDecimalPoint && (endPos - numOffset) <= 19) { // No more than 18 digits plus one decimal point (which // should fit a long) long lv = 0L; int expo = -(endPos - (decimalPointPos + 1)); int vi = numOffset; for (; vi < decimalPointPos; ++vi) { lv = checked ((lv * 10) + (int)(str[vi] - '0')); } for (vi = decimalPointPos + 1; vi < endPos; ++vi) { lv = checked ((lv * 10) + (int)(str[vi] - '0')); } if (negative) { lv = -lv; } if (!negative || lv != 0) { CBORObject cbor = CBORObject.NewArray() .Add(expo).Add(lv); return(CBORObject.FromObjectAndTag(cbor, 4)); } } EDecimal ed = EDecimal.FromString( str, initialOffset, endPos - initialOffset); if (ed.IsZero && negative) { if (preserveNegativeZero && ed.Exponent.IsZero) { // TODO: In next major version, use EDecimal return(CBORObject.FromFloatingPointBits(0x8000, 2)); } else if (!preserveNegativeZero) { ed = ed.Negate(); } } return(CBORObject.FromObject(ed)); } else if (kind == JSONOptions.ConversionMode.Double) { double dbl = EFloat.FromString( str, initialOffset, endPos - initialOffset, EContext.Binary64).ToDouble(); if (!preserveNegativeZero && dbl == 0.0) { dbl = 0.0; } return(CBORObject.FromObject(dbl)); } else if (kind == JSONOptions.ConversionMode.Decimal128) { EDecimal ed = EDecimal.FromString( str, initialOffset, endPos - initialOffset, EContext.Decimal128); if (!preserveNegativeZero && ed.IsNegative && ed.IsZero) { ed = ed.Negate(); } return(CBORObject.FromObject(ed)); } else if (kind == JSONOptions.ConversionMode.IntOrFloatFromDouble) { double dbl = EFloat.FromString( str, initialOffset, endPos - initialOffset, EContext.Binary64).ToDouble(); if (!Double.IsNaN(dbl) && dbl >= -9007199254740991.0 && dbl <= 9007199254740991.0 && Math.Floor(dbl) == dbl) { var idbl = (long)dbl; return(CBORObject.FromObject(idbl)); } return(CBORObject.FromObject(dbl)); } else if (kind == JSONOptions.ConversionMode.IntOrFloat) { EContext ctx = EContext.Binary64.WithBlankFlags(); double dbl = EFloat.FromString( str, initialOffset, endPos - initialOffset, ctx).ToDouble(); if ((ctx.Flags & EContext.FlagInexact) != 0) { // Inexact conversion to double, meaning that the string doesn't // represent an integer in [-(2^53)+1, 2^53), which is representable // exactly as double, so treat as ConversionMode.Double if (!preserveNegativeZero && dbl == 0.0) { dbl = 0.0; } return(CBORObject.FromObject(dbl)); } else { // Exact conversion; treat as ConversionMode.IntToFloatFromDouble if (!Double.IsNaN(dbl) && dbl >= -9007199254740991.0 && dbl <= 9007199254740991.0 && Math.Floor(dbl) == dbl) { var idbl = (long)dbl; return(CBORObject.FromObject(idbl)); } return(CBORObject.FromObject(dbl)); } } else { throw new ArgumentException("Unsupported conversion kind."); } }
/// <include file='../../docs.xml' /// path='docs/doc[@name="M:PeterO.Cbor.CBORDataUtilities.ParseJSONNumber(System.String,System.Boolean,System.Boolean,System.Boolean)"]/*'/> public static CBORObject ParseJSONNumber( string str, bool integersOnly, bool positiveOnly, bool preserveNegativeZero) { if (String.IsNullOrEmpty(str)) { return(null); } var offset = 0; var negative = false; if (str[0] == '-' && !positiveOnly) { negative = true; ++offset; } var mantInt = 0; FastInteger2 mant = null; var mantBuffer = 0; var mantBufferMult = 1; var expBuffer = 0; var expBufferMult = 1; var haveDecimalPoint = false; var haveDigits = false; var haveDigitsAfterDecimal = false; var haveExponent = false; var newScaleInt = 0; FastInteger2 newScale = null; int i = offset; // Ordinary number if (i < str.Length && str[i] == '0') { ++i; haveDigits = true; if (i == str.Length) { if (preserveNegativeZero && negative) { return(CBORObject.FromObject( EDecimal.NegativeZero)); } return(CBORObject.FromObject(0)); } if (!integersOnly) { if (str[i] == '.') { haveDecimalPoint = true; ++i; } else if (str[i] == 'E' || str[i] == 'e') { haveExponent = true; } else { return(null); } } else { return(null); } } for (; i < str.Length; ++i) { if (str[i] >= '0' && str[i] <= '9') { var thisdigit = (int)(str[i] - '0'); if (mantInt > MaxSafeInt) { if (mant == null) { mant = new FastInteger2(mantInt); mantBuffer = thisdigit; mantBufferMult = 10; } else { if (mantBufferMult >= 1000000000) { mant.Multiply(mantBufferMult).AddInt(mantBuffer); mantBuffer = thisdigit; mantBufferMult = 10; } else { mantBufferMult *= 10; mantBuffer = (mantBuffer << 3) + (mantBuffer << 1); mantBuffer += thisdigit; } } } else { mantInt *= 10; mantInt += thisdigit; } haveDigits = true; if (haveDecimalPoint) { haveDigitsAfterDecimal = true; if (newScaleInt == Int32.MinValue) { newScale = newScale ?? (new FastInteger2(newScaleInt)); newScale.AddInt(-1); } else { --newScaleInt; } } } else if (!integersOnly && str[i] == '.') { if (!haveDigits) { // no digits before the decimal point return(null); } if (haveDecimalPoint) { return(null); } haveDecimalPoint = true; } else if (!integersOnly && (str[i] == 'E' || str[i] == 'e')) { haveExponent = true; ++i; break; } else { return(null); } } if (!haveDigits || (haveDecimalPoint && !haveDigitsAfterDecimal)) { return(null); } if (mant != null && (mantBufferMult != 1 || mantBuffer != 0)) { mant.Multiply(mantBufferMult).AddInt(mantBuffer); } if (haveExponent) { FastInteger2 exp = null; var expInt = 0; offset = 1; haveDigits = false; if (i == str.Length) { return(null); } if (str[i] == '+' || str[i] == '-') { if (str[i] == '-') { offset = -1; } ++i; } for (; i < str.Length; ++i) { if (str[i] >= '0' && str[i] <= '9') { haveDigits = true; var thisdigit = (int)(str[i] - '0'); if (expInt > MaxSafeInt) { if (exp == null) { exp = new FastInteger2(expInt); expBuffer = thisdigit; expBufferMult = 10; } else { if (expBufferMult >= 1000000000) { exp.Multiply(expBufferMult).AddInt(expBuffer); expBuffer = thisdigit; expBufferMult = 10; } else { // multiply expBufferMult and expBuffer each by 10 expBufferMult = (expBufferMult << 3) + (expBufferMult << 1); expBuffer = (expBuffer << 3) + (expBuffer << 1); expBuffer += thisdigit; } } } else { expInt *= 10; expInt += thisdigit; } } else { return(null); } } if (!haveDigits) { return(null); } if (exp != null && (expBufferMult != 1 || expBuffer != 0)) { exp.Multiply(expBufferMult).AddInt(expBuffer); } if (offset >= 0 && newScaleInt == 0 && newScale == null && exp == null) { newScaleInt = expInt; } else if (exp == null) { newScale = newScale ?? (new FastInteger2(newScaleInt)); if (offset < 0) { newScale.SubtractInt(expInt); } else if (expInt != 0) { newScale.AddInt(expInt); } } else { newScale = newScale ?? (new FastInteger2(newScaleInt)); if (offset < 0) { newScale.Subtract(exp); } else { newScale.Add(exp); } } } if (i != str.Length) { // End of the string wasn't reached, so isn't a number return(null); } if ((newScale == null && newScaleInt == 0) || (newScale != null && newScale.Sign == 0)) { // No fractional part if (mant != null && mant.CanFitInInt32()) { mantInt = mant.AsInt32(); mant = null; } if (mant == null) { // NOTE: mantInt can only be 0 or greater, so overflow is impossible #if DEBUG if (mantInt < 0) { throw new ArgumentException("mantInt (" + mantInt + ") is less than 0"); } #endif if (negative) { mantInt = -mantInt; if (preserveNegativeZero && mantInt == 0) { return(CBORObject.FromObject( EDecimal.NegativeZero)); } } return(CBORObject.FromObject(mantInt)); } else { EInteger bigmant2 = mant.AsBigInteger(); if (negative) { bigmant2 = -(EInteger)bigmant2; } return(CBORObject.FromObject(bigmant2)); } } else { EInteger bigmant = (mant == null) ? ((EInteger)mantInt) : mant.AsBigInteger(); EInteger bigexp = (newScale == null) ? ((EInteger)newScaleInt) : newScale.AsBigInteger(); if (negative) { bigmant = -(EInteger)bigmant; } EDecimal edec; edec = EDecimal.Create( bigmant, bigexp); if (negative && preserveNegativeZero && bigmant.IsZero) { EDecimal negzero = EDecimal.NegativeZero; negzero = negzero.Quantize(bigexp, null); edec = negzero.Subtract(edec); } return(CBORObject.FromObject(edec)); } }
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"); }
public static CBORObject Subtract(CBORObject a, CBORObject b) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (a.Type != CBORType.Number) { throw new ArgumentException("a.Type (" + a.Type + ") is not equal to " + CBORType.Number); } if (b.Type != CBORType.Number) { throw new ArgumentException("b.Type (" + b.Type + ") is not equal to " + CBORType.Number); } object objA = a.ThisItem; object objB = b.ThisItem; int typeA = a.ItemType; int typeB = b.ItemType; if (typeA == CBORObject.CBORObjectTypeInteger && typeB == CBORObject.CBORObjectTypeInteger) { var valueA = (long)objA; var valueB = (long)objB; if ((valueB < 0 && Int64.MaxValue + valueB < valueA) || (valueB > 0 && Int64.MinValue + valueB > valueA)) { // would overflow, convert to EInteger return(CBORObject.FromObject(((EInteger)valueA) - (EInteger)valueB)); } return(CBORObject.FromObject(valueA - valueB)); } if (typeA == CBORObject.CBORObjectTypeExtendedRational || typeB == CBORObject.CBORObjectTypeExtendedRational) { ERational e1 = CBORObject.GetNumberInterface(typeA).AsExtendedRational(objA); ERational e2 = CBORObject.GetNumberInterface(typeB).AsExtendedRational(objB); return(CBORObject.FromObject(e1.Subtract(e2))); } if (typeA == CBORObject.CBORObjectTypeExtendedDecimal || typeB == CBORObject.CBORObjectTypeExtendedDecimal) { EDecimal e1 = CBORObject.GetNumberInterface(typeA).AsExtendedDecimal(objA); EDecimal e2 = CBORObject.GetNumberInterface(typeB).AsExtendedDecimal(objB); return(CBORObject.FromObject(e1.Subtract(e2))); } if (typeA == CBORObject.CBORObjectTypeExtendedFloat || typeB == CBORObject.CBORObjectTypeExtendedFloat || typeA == CBORObject.CBORObjectTypeDouble || typeB == CBORObject.CBORObjectTypeDouble || typeA == CBORObject.CBORObjectTypeSingle || typeB == CBORObject.CBORObjectTypeSingle) { EFloat e1 = CBORObject.GetNumberInterface(typeA).AsExtendedFloat(objA); EFloat e2 = CBORObject.GetNumberInterface(typeB).AsExtendedFloat(objB); return(CBORObject.FromObject(e1.Subtract(e2))); } else { EInteger b1 = CBORObject.GetNumberInterface(typeA).AsEInteger(objA); EInteger b2 = CBORObject.GetNumberInterface(typeB).AsEInteger(objB); return(CBORObject.FromObject(b1 - (EInteger)b2)); } }
private CBORObject NextJSONValue( int firstChar, int[] nextChar, int depth) { string str; int c = firstChar; CBORObject obj = null; if (c < 0) { this.reader.RaiseError("Unexpected end of data"); } switch (c) { case '"': { // Parse a string // The tokenizer already checked the string for invalid // surrogate pairs, so just call the CBORObject // constructor directly obj = CBORObject.FromRaw(this.NextJSONString()); nextChar[0] = SkipWhitespaceJSON(this.reader); return(obj); } case '{': { // Parse an object obj = this.ParseJSONObject(depth + 1); nextChar[0] = SkipWhitespaceJSON(this.reader); return(obj); } case '[': { // Parse an array obj = this.ParseJSONArray(depth + 1); nextChar[0] = SkipWhitespaceJSON(this.reader); return(obj); } case 't': { // Parse true if (this.reader.ReadChar() != 'r' || this.reader.ReadChar() != 'u' || this.reader.ReadChar() != 'e') { this.reader.RaiseError("Value can't be parsed."); } nextChar[0] = SkipWhitespaceJSON(this.reader); return(CBORObject.True); } case 'f': { // Parse false if (this.reader.ReadChar() != 'a' || this.reader.ReadChar() != 'l' || this.reader.ReadChar() != 's' || this.reader.ReadChar() != 'e') { this.reader.RaiseError("Value can't be parsed."); } nextChar[0] = SkipWhitespaceJSON(this.reader); return(CBORObject.False); } case 'n': { // Parse null if (this.reader.ReadChar() != 'u' || this.reader.ReadChar() != 'l' || this.reader.ReadChar() != 'l') { this.reader.RaiseError("Value can't be parsed."); } nextChar[0] = SkipWhitespaceJSON(this.reader); return(CBORObject.Null); } case '-': { // Parse a negative number var lengthTwo = true; c = this.reader.ReadChar(); if (c < '0' || c > '9') { this.reader.RaiseError("JSON number can't be parsed."); } int cval = -(c - '0'); int cstart = c; StringBuilder sb = null; c = this.reader.ReadChar(); while (c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') || c == 'e' || c == 'E') { if (lengthTwo) { sb = new StringBuilder(); sb.Append((char)'-'); sb.Append((char)cstart); lengthTwo = false; } sb.Append((char)c); c = this.reader.ReadChar(); } if (lengthTwo) { obj = cval == 0 ? CBORDataUtilities.ParseJSONNumber("-0", true, false, true) : CBORObject.FromObject(cval); } else { str = sb.ToString(); obj = CBORDataUtilities.ParseJSONNumber(str); if (obj == null) { this.reader.RaiseError("JSON number can't be parsed. " + str); } } if (c == -1 || (c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)) { nextChar[0] = c; } else { nextChar[0] = SkipWhitespaceJSON(this.reader); } return(obj); } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { // Parse a number var lengthOne = true; int cval = c - '0'; int cstart = c; StringBuilder sb = null; c = this.reader.ReadChar(); while (c == '-' || c == '+' || c == '.' || (c >= '0' && c <= '9') || c == 'e' || c == 'E') { if (lengthOne) { sb = new StringBuilder(); sb.Append((char)cstart); lengthOne = false; } sb.Append((char)c); c = this.reader.ReadChar(); } if (lengthOne) { obj = CBORObject.FromObject(cval); } else { str = sb.ToString(); obj = CBORDataUtilities.ParseJSONNumber(str); if (obj == null) { this.reader.RaiseError("JSON number can't be parsed. " + str); } } if (c == -1 || (c != 0x20 && c != 0x0a && c != 0x0d && c != 0x09)) { nextChar[0] = c; } else { nextChar[0] = SkipWhitespaceJSON(this.reader); } return(obj); } default: this.reader.RaiseError("Value can't be parsed."); break; } return(null); }
public static CBORObject FromObject(ulong value) { return(CBORObject.FromObject(UInt64ToEInteger(value))); }
/// <summary>Converts a date/time in the form of a year, month, day, /// hour, minute, second, fractional seconds, and time offset to a CBOR /// object.</summary> /// <param name='bigYear'>The parameter <paramref name='bigYear'/> is a /// Numbers.EInteger object.</param> /// <param name='lesserFields'>An array that will store the fields /// (other than the year) of the date and time. See the /// TryGetDateTimeFields method for information on the "lesserFields" /// parameter.</param> /// <returns>A CBOR object encoding the given date fields according to /// the conversion type used to create this date converter.</returns> /// <exception cref='ArgumentNullException'>The parameter <paramref /// name='bigYear'/> or <paramref name='lesserFields'/> is /// null.</exception> /// <exception cref='PeterO.Cbor.CBORException'>An error occurred in /// conversion.</exception> public CBORObject DateTimeFieldsToCBORObject(EInteger bigYear, int[] lesserFields) { if (bigYear == null) { throw new ArgumentNullException(nameof(bigYear)); } if (lesserFields == null) { throw new ArgumentNullException(nameof(lesserFields)); } if (lesserFields.Length < 7) { throw new ArgumentException("\"lesserFields\" + \"'s length\" (" + lesserFields.Length + ") is not greater or equal to 7"); } try { switch (this.convType) { case ConversionType.TaggedString: { string str = CBORUtilities.ToAtomDateTimeString(bigYear, lesserFields); return(CBORObject.FromObjectAndTag(str, 0)); } case ConversionType.TaggedNumber: case ConversionType.UntaggedNumber: try { var status = new int[1]; EFloat ef = CBORUtilities.DateTimeToIntegerOrDouble( bigYear, lesserFields, status); if (status[0] == 0) { return(this.convType == ConversionType.TaggedNumber ? CBORObject.FromObjectAndTag(ef.ToEInteger(), 1) : CBORObject.FromObject(ef.ToEInteger())); } else if (status[0] == 1) { return(this.convType == ConversionType.TaggedNumber ? CBORObject.FromFloatingPointBits(ef.ToDoubleBits(), 8).WithTag(1) : CBORObject.FromFloatingPointBits(ef.ToDoubleBits(), 8)); } else { throw new CBORException("Too big or small to fit an integer" + "\u0020or" + "\u0020floating-point number"); } } catch (ArgumentException ex) { throw new CBORException(ex.Message, ex); } default: throw new CBORException("Internal error"); } } catch (ArgumentException ex) { throw new CBORException(ex.Message, ex); } }
public static byte[] CtapCanonicalEncode(CBORObject a) { CBORObject cbor = a.Untag(); CBORType valueAType = cbor.Type; try { if (valueAType == CBORType.Array) { using (var ms = new MemoryStream()) { CBORObject.WriteValue(ms, 4, cbor.Count); for (var i = 0; i < cbor.Count; ++i) { byte[] bytes = CtapCanonicalEncode(cbor[i]); ms.Write(bytes, 0, bytes.Length); } return(ms.ToArray()); } } else if (valueAType == CBORType.Map) { var sortedKeys = new List <CBORObject>(); foreach (CBORObject key in cbor.Keys) { sortedKeys.Add(key); } sortedKeys.Sort(new CtapComparer()); using (var ms = new MemoryStream()) { CBORObject.WriteValue(ms, 5, cbor.Count); foreach (CBORObject key in sortedKeys) { byte[] bytes = CtapCanonicalEncode(key); ms.Write(bytes, 0, bytes.Length); bytes = CtapCanonicalEncode(cbor[key]); ms.Write(bytes, 0, bytes.Length); } return(ms.ToArray()); } } } catch (IOException ex) { throw new InvalidOperationException(ex.ToString(), ex); } if (valueAType == CBORType.SimpleValue || valueAType == CBORType.Boolean || valueAType == CBORType.ByteString || valueAType == CBORType.TextString) { return(cbor.EncodeToBytes(CBOREncodeOptions.Default)); } else if (valueAType == CBORType.Number) { if (cbor.CanFitInInt64()) { return(cbor.EncodeToBytes(CBOREncodeOptions.Default)); } else { cbor = CBORObject.FromObject(cbor.AsDouble()); return(cbor.EncodeToBytes(CBOREncodeOptions.Default)); } } else { throw new ArgumentException("Invalid CBOR type."); } }